Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

polymorphism-like handling of parameters - simple OO?

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.

like image 249
user1922401 Avatar asked Oct 04 '22 02:10

user1922401


1 Answers

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.

like image 144
confusopoly Avatar answered Oct 22 '22 20:10

confusopoly