instanceof与多态

时间:2011-05-25 03:04:28

标签: 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 }

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

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) { }

4 个答案:

答案 0 :(得分:5)

您可以将parseShape移动到每个Shape类中。或者,您可以使用访客模式。在this thread的解决方案中显示了一个巧妙的技巧,它避免了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)。

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

答案 1 :(得分:4)

如果您在parseShape()中声明了Shape方法,则可以在TriangleRectangle中覆盖该方法。

那是:

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()