我遇到了instanceof
运营商的麻烦。我试图避免它。基本上,我有以下结构:
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 }
我正在做的关键点是:我想对函数进行参数重载,但它不能正常工作(编译错误)。我试图避免:
void parseShape(Shape s)
{
if (s instanceof Triangle) ...
}
更新:似乎共识是创建一个基类方法:parseShape()来做 吊装。我想澄清一下我的问题:这个问题的动机是与观察者模式有关。假设我有以下Observer对象有效负载方法:
public void update(Observable obj, Shape objectPayload){}
// note: the objectPayload is usually of type Object
而不是执行:
public void update(Observable obj, Shape objectPayload)
{
if (objectPayload instanceof Triangle)
// do stuff
else if (objectPayload instanceof Rectangle)
// etc
}
我想这样做:
public void update(Observable obj, Shape objectPayload)
{
parseShape(objectPayload);
}
void parseShape(Triangle t) { } // do stuff
void parseShape(Rectangle t) { }
答案 0 :(得分:5)
您可以将parseShape
移动到每个Shape类中。或者,您可以使用访客模式。在this thread的解决方案中显示了一个巧妙的技巧,它避免了Java中完整访问者模式的复杂性。
更新:
以下是访客模式的配方:
声明一个接口:
public interface ShapeVisitor { visit(Triangle); visit(Rectangle); // ... }
在Shape
中,声明一个抽象方法acceptVisitor
:
class Shape { public abstract void acceptVisitor(ShapeVisitor visitor); }
在每个具体课程中,实施acceptVisitor
:
class Triangle extends Shape { public void acceptVisitor(ShapeVisitor visitor) { visitor.visit(this); } }
声明您的ParseVisitor
课程实施ShapeVisitor
并实施所有必需的方法(只需将每个parseShape
方法重命名为visit
)。
关于这一点的好处是,首先,它将解析代码保留在Shape层次结构之外,并将其集中在一个单独的解析类中;第二,如果你以后决定需要做一些其他的操作(比如说渲染),你可以应用相同的模式而不用改变任何Shape类。这种方法的重大缺点是,如果您决定添加另一个ShapeVisitor
子类,则必须更改实现Shape
的所有类。
答案 1 :(得分:4)
如果您在parseShape()
中声明了Shape
方法,则可以在Triangle
和Rectangle
中覆盖该方法。
那是:
ShapeParser s;
while (s.hasNext())
// Calls the proper implementation of parseShape()
s.next().parseShape();
答案 2 :(得分:1)
嗯,在基类中添加一个解析方法,然后循环遍历形状列表并调用s.parse()?
答案 3 :(得分:0)
我认为错误是因为s.next()返回Shape。逻辑的事情是 添加parse()方法以形成并调用s.parse()