我在使用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) { }

最佳答案

您可以将parseShape移动到每个Shape类中。或者,您可以使用“访客”模式。 this thread解决方案中显示了一个巧妙的反射技巧,可以避免Java中完整访问者模式的复杂性。

更新:

这是访客模式的秘诀:

  • 声明一个接口(interface):

    公共(public)接口(interface)ShapeVisitor {
    visit(三角形);
    visit(Rectangle);
    //...
    }
  • Shape中,声明一个抽象方法acceptVisitor:

    类Shape {
    公共(public)抽象无效acceptVisitor(ShapeVisitor visitor);
    }
  • 在每个具体的类中,实现acceptVisitor:

    类Triangle扩展Shape {
    公共(public)无效acceptVisitor(ShapeVisitor访问者){
    visitor.visit(this);
    }
    }
  • 声明您的ParseVisitor类以实现ShapeVisitor并实现所有必需的方法(只需将每个parseShape方法重命名为visit)。

  • 这样做的好处是,首先,它将解析代码保留在Shape层次结构之外,并将其集中在一个单独的解析类中;然后,将其集中在一个单独的解析类中。其次,如果您以后决定需要执行其他操作(例如渲染),则可以应用相同的图案,而无需更改任何Shape类。这种方法最大的缺点是,如果决定添加另一个ShapeVisitor子类,则必须更改所有实现Shape的类。

    关于java - instanceof与多态,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/6119087/

    10-09 00:11