Reputation:
I am having troubles with the instanceof
operator. I'm trying to avoid it. Basically, I have the following structure:
class Shape {}
class Triangle extends Shape {}
class Rectangle extends Shape {}
ShapeParser s;
while (s.hasNext())
parseShape(s.next()); // returns a Shape object
void parseShape(Triangle t) { // do stuff } // KEY POINT HERE
void parseShape(Rectangle t) { // etc }
The key point I'm making is: I want to do a parameter overload of the function, but it's not working as I intend it to (compile-error). I am trying to avoid:
void parseShape(Shape s)
{
if (s instanceof Triangle) ...
}
UPDATE: it seems that the consensus is to create a base class method: parseShape() to do the lifting. I wanted to clarify my question: the motivation of this question is relative to the observer pattern. Suppose I have the following Observer object payload method:
public void update(Observable obj, Shape objectPayload){}
// note: the objectPayload is usually of type Object
Instead of performing:
public void update(Observable obj, Shape objectPayload)
{
if (objectPayload instanceof Triangle)
// do stuff
else if (objectPayload instanceof Rectangle)
// etc
}
I want to do:
public void update(Observable obj, Shape objectPayload)
{
parseShape(objectPayload);
}
void parseShape(Triangle t) { } // do stuff
void parseShape(Rectangle t) { }
Upvotes: 5
Views: 2722
Reputation: 234807
You can move the parseShape
into each Shape class. Alternatively, you can use the Visitor pattern. There's a neat trick with reflection shown in the solution to this thread that avoids the complexity of a full visitor pattern in Java.
UPDATE:
Here's a recipe for the visitor pattern:
Declare an interface:
public interface ShapeVisitor { visit(Triangle); visit(Rectangle); // ... }
In Shape
, declare an abstract method acceptVisitor
:
class Shape { public abstract void acceptVisitor(ShapeVisitor visitor); }
In each concrete class, implement acceptVisitor
:
class Triangle extends Shape { public void acceptVisitor(ShapeVisitor visitor) { visitor.visit(this); } }
Declare your ParseVisitor
class to implement ShapeVisitor
and implement all the required methods (simply rename each of the parseShape
methods to visit
).
The nice things about this are, first, it keeps the parsing code out of your Shape hierarchy and centralizes it in a separate parsing class; second, if you later decide that you need to do some other operation (like, say, render), you can apply the same pattern without ever changing any Shape class. The big down side of this approach is that you will have to change all classes that implement ShapeVisitor
if you decide to add another Shape
subclass.
Upvotes: 4
Reputation: 24722
I assume that the error is because s.next() returns Shape. Logical thing would be to add parse() method to shape and call s.parse()
Upvotes: 0
Reputation: 59586
If your parseShape()
method were declared in Shape
, it could be overridden in Triangle
and Rectangle
.
That is:
ShapeParser s;
while (s.hasNext())
// Calls the proper implementation of parseShape()
s.next().parseShape();
Upvotes: 4
Reputation: 11733
Um, add a parse method to the base class then just loop and iterate through the list of shapes and call s.parse()?
Upvotes: 1