instanceof与多态

Car*_*ndo 5 java polymorphism

我遇到了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 }
Run Code Online (Sandbox Code Playgroud)

我正在做的关键点是:我想要对函数执行参数重载,但是它不能正常工作(编译错误).我试图避免:

void parseShape(Shape s)
{
     if (s instanceof Triangle) ...
}
Run Code Online (Sandbox Code Playgroud)

更新:似乎共识是创建一个基类方法:parseShape()来完成提升.我想澄清一下我的问题:这个问题的动机是与观察者模式有关.假设我有以下Observer对象有效负载方法:

    public void update(Observable obj, Shape objectPayload){} 
// note: the objectPayload is usually of type Object
Run Code Online (Sandbox Code Playgroud)

而不是执行:

public void update(Observable obj, Shape objectPayload)
{
       if (objectPayload instanceof Triangle)
          // do stuff
       else if (objectPayload instanceof Rectangle)
          // etc
}
Run Code Online (Sandbox Code Playgroud)

我想要做:

public void update(Observable obj, Shape objectPayload)
{
       parseShape(objectPayload);
}

    void parseShape(Triangle t) {  } // do stuff
    void parseShape(Rectangle t) { }
Run Code Online (Sandbox Code Playgroud)

Ted*_*opp 5

您可以移动parseShape到每个Shape类中.或者,您可以使用访客模式.这个线程的解决方案中显示了反射的巧妙技巧,避免了Java中完整访问者模式的复杂性.

更新:

这是访客模式的配方:

  1. 声明一个接口:

    public interface ShapeVisitor {  
        visit(Triangle);  
        visit(Rectangle);  
        // ...  
    }
    
  2. Shape,声明一个抽象方法acceptVisitor:

    class Shape {
        public abstract void acceptVisitor(ShapeVisitor visitor);
    }
    
  3. 在每个具体类中,实现acceptVisitor:

    class Triangle extends Shape {
        public void acceptVisitor(ShapeVisitor visitor) {
            visitor.visit(this);
        }
    }
    
  4. 声明您的ParseVisitor类以实现ShapeVisitor和实现所有必需的方法(只需将每个parseShape方法重命名为visit).

关于这一点的好处是,首先,它将解析代码保留在Shape层次结构之外,并将其集中在一个单独的解析类中; 第二,如果您以后决定需要进行其他操作(比如说渲染),则可以应用相同的模式而无需更改任何Shape类.这种方法的重大缺点是,ShapeVisitor如果您决定添加另一个Shape子类,则必须更改所有实现的类.