JB101UK
JB101UK

Reputation: 33

Interface Method for Class Properties Returning Different Number of Arguments?

I have a single interface: IShape2D, with methods such as Area(), Perimeter() etc.

I also have two classes: Rectangle and Circle.

Both of these classes implement IShape2D. But they also have local properties depending on their shape. For example, Rectangle has a width and depth, whereas Circle only has a diameter.

I am trying to pass (using polymorphism) object instantiations of either Rectangle or Circle to another class constructor so that I can access their methods.

The class constructor expects the following: ClassA(IShape2D _2dObject) I can use Area(), Perimeter() without a problem, since IShape2D has a method which both sub-shapes implement.

My problem: I want to access the local properties of these shapes, so that regardless of whether a Circle or Rectangle is passed, I can query either the width and depth, OR the diameter.

I understand that I need to add another method to the interface, something like GetDimensions(). However, Rectangle would return 2 values (width, depth - both type double), whilst Circle would only return 1 (diameter).

I can't work out how to define the Interface Method's Return type in the Signature so that I both sub-shapes can implement the single method but return their respective properties.

I've tried various approaches to accommodate returning different number of arguments from the two different sub-shapes.

The best approach I thought would be to return a ValueTuple in the interface signature, but I would need to provide the number of return arguments in the signature, which for a rectangle would be ValueTuple(double, double) and for a circle would be ValueTuple(double).

//Start of interface.
public interface IShape2D {
   double Area;
   double Perimeter;
   ValueTuple<double, double> getDimensions();
}

//Start of rectangle class.
public class Rectangle : IShape2D
{

   public double Width {get; set;}
   public double Depth {get; set;}

   public Rectangle(double _width, double _depth) {
      this.Width = _width;
      this.Depth = _depth;
   }

   public double Area
   { get 
       {  //return calculation result for area;  }
   }

   public double Perimeter 
   { get 
       {  //return calculation result for perimeter;  }
   }

   public ValueTuple<double, double> getDimensions()
   {
      return //tuple containing both width and depth
   }
}

//Start of circle class.
public class Circle : IShape2D
{

   public double Diameter {get; set;}

   public Circle(double _diameter) {
       this.Diameter = _diameter;
   }

   public double Area
   { get 
       {  //return calculation result for area;  }
   }

   public double Perimeter 
   { get 
       {  //return calculation result for perimeter;  }
   }

   public ValueTuple<double> getDimensions()
   {
      return //tuple containing diameter
   }
}

public class NewClass(IShape2D _2dObject) 
{
   //this class receives either rectangle or circle object, with access to local properties and methods.  
}

Upvotes: 0

Views: 134

Answers (2)

ChiefTwoPencils
ChiefTwoPencils

Reputation: 13940

I probably wouldn't do this. It seems as though the shape types will inevitably converge in the code if you try to get at their private parts in areas where you're expecting the base type. But if you insist, you probably want to make a single return type that's flexible; maybe a Dictionary<string, double>, like so:

public class Rectangle : IShape2D
{

   public double Width {get; set;}
   public double Depth {get; set;}

   ...

   public Dictionary<string, double> getDimensions()
   {
       return new Dictionary<string, double>
       {
           { nameof(Width), Width },
           { nameof(Depth), Depth }
       };
   }
}

public class Circle : IShape2D
{

   public double Diameter {get; set;}

   ...

   public Dictionary<string, double> getDimensions()
   {
       return new Dictionary<string, double>
       {
           { nameof(Diameter), Diameter }
       };
   }
}

This way, you can get the keys and their count as well as the values.

Upvotes: 1

Corentin Pane
Corentin Pane

Reputation: 4943

The point of interfaces is to abstract yourself from specific implementations of each shape you have. If you still need a method GetDimensions() on all shapes, maybe you could return a List<double> of dimensions, even though I doubt there are any geometric applications to it.

Each shape could return a List with different number of items.

Upvotes: 0

Related Questions