I am sure this must have been asked before but I cannot seem to find a similar example. I understand well polymorphism and method overloading, but here is a seemingly simple scenario with a solution that escapes me:
let's say I have a base class with several derived classes. I will use shapes for this example
base Shape
derived Circle extends Shape
derived LineSeg extends Shape
etc.
Now, shape has a method called intersect(other) that tests against another shape to see if they intersect. With polymorphism it is easy to see how Circle, LineSeg, etc., can implement their own "intersect" methods, and, with method overloading, I can easily implement all needed combinations. e.g.,
Circle.intersect(LineSeg)
Circle.intersect(Circle)
LineSeg.intersect(Circle)
etc.
so far so good.
the problem is, if I keep a central list of shapes, I want to do this:
for some shape s
Foreach shape in Shapes
if (s.intersect(shape)) - do something
Currently, I am not sure how this is possible, since the method overloading selects the "intersect" method to match the base type Shape, and not the appropriate parameter type. How can I make this without an if-else chain checking the types and down-casting?
BTW, I am using Java, but I am not sure that the language is entirely relevant since it seems to be a basic design question. Seems so simple, what am I missing?
Thanks!
Solved below (Thanks!), see details there. Basically, by having a callback in the derived classes that then calls the appropriate method (a visitor pattern?), you can use the "this" keyword to invoke the proper intersect method, as it has the proper type needed.
My first thought was the visitor pattern, pretty much give every Shape two methods, one I'll call intersect(Shape)
and one doIntersect()
method per Shape type.
It would look about like this:
interface Shape {
public abstract Intersection intersect(Shape other);
public abstract Intersection doIntersect(Circle circle);
public abstract Intersection doIntersect(LineSeg line);
}
class LineSeg implements Shape {
@Override
public Intersection intersect(Shape other) {
return other.doIntersect(this);
}
Intersection doIntersect(Circle circle) {
// Code to intersect with Circle
}
Intersection doIntersect(LineSeg other) {
// Code to intersect with another Lineseg
}
}
class Circle implements Shape {
@Override
public Intersection intersect(Shape other) {
return other.doIntersect(this);
}
public Intersection doIntersect(Circle other) {
// Code to intersect with another Circle
}
public Intersection doIntersect(LineSeg segment) {
// Code to intersect with LineSeg
}
}
You might want the doIntersect methods to be package private or chose different names than these though.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With