Reputation: 3302
I have 3 different type of shape diagrams say Rectangle
, Cube
, Circle
, I want to define classes for them such that
All classes would have Title & Color property/method,
Circle & Rectangle would have additional method Area,
Similarly Cube would have Volume method rather than Area method.
There is a method in which I get the reference of of 'object', following is sample method
public void ShapeClicked(object obj)
{
// Check the type of obj & type cast it accordingly & call the method on that object
object obj = new Circle();
if (obj is Circle)
{
Circle circleObj = (Circle)obj;
circleObj.GetArea();
}
else if (obj is Rectangle)
{
Rectangle rectangleObj = (Rectangle)obj;
rectangleObj.GetArea();
}
else if (obj is Cube)
{
Cube cubeObj = (Cube)obj;
cubeObj.GetVolume();
}
}
How can I design my classes such that in 'ShapeClicked(object obj)' method
a) I need not to check the type every time (should happen at run time), (This is important for me because I have many methods like 'ShapeClicked' which requires me checking the type)
b) if object is of Circle then it would get only Area method, similarly for Cube object it would get only Volume method.
I can think of two approaches
Put all the methods & properties in base class & only override required methods in derive class. Create a Factory method/class which would return the reference of Base class. With this approach my 'b' requirement does not meet
Put only common methods/property (like color) in base class & add additional methods in derive class. This does not solve #a :(
Can anybody suggest me some solution which solves both #a & #b
Upvotes: 2
Views: 1474
Reputation: 101150
Introduce a new interface.
public interface IMeasurable
{
someReturnType GetMeasure();
}
public class Circle : IMeasurable
{
//some other methods
public someReturnType GetMeasure() { return GetArea(); }
}
public class Cube : IMeasurable
{
//some other methods
public someReturnType GetMeasure() { return GetVolume(); }
}
Update
Your method would look like:
public void ShapeClicked(object obj)
{
var measurable = obj as IMeasurable;
if (measurable == null)
throw new InvalidOperationException(string.Format("We can only work with measurable types, which {0} is not.", obj.GetType());
var measure = measurable.GetMeasure();
}
Upvotes: 3
Reputation: 39615
Using base types is good when you have common behaviour you want to inherit. In your case, you really have a common way to interact with your types, but how those types behave is quite different.
In this case what you're really trying to do is define a common interface so you can treat your types similarly.
I would define the following:
public interface IShape
{
string Title { get; }
string Color { get; }
}
public interface I2DShape : IShape
{
int GetArea();
}
public interface I3DShape : IShape
{
int GetVolume();
}
You can then implement I2DShape
on Circle
and Rectangle
, and I3DShape
on Cube
. Your method then can be implemented as such:
public void ShapeClicked(IShape shape)
{
var shape2d = shape as I2DShape;
if(shape2d != null)
{
shape2d.GetArea();
return;
}
var shape3d = shape as I3DShape;
if(shape3d != null)
{
shape3d.GetVolume();
}
}
You still need to check whether a shape is 2D or 3D, but that's just because we've defined Area and Volume as separate things. If you wanted to define them as a singular thing, you could put that on the base interface and have all your types implement that interface.
Upvotes: 0
Reputation: 258568
Yes.
You should have a base class for all shapes and have a method ShapeClicked()
in the base class.
class Shape
{
-tile
-color
ShapeClicked()
}
class PlanarShape extends Shape
{
-area
Area()
}
class SpatialShape extends Shape
{
-volume
Volume()
}
class Circle extends PlanarShape
{
ShapeClicked()
}
class Rectangle extends PlanarShape
{
ShapeClicked()
}
class Cube extends SpatialShape
{
ShapeClicked()
}
Then you modify the function as:
public void ShapeClicked(Shape obj)
{
obj.ShapeClicked();
}
Via polymorphism, your call will be directed to the right class.
Upvotes: 0