java - instanceof 与多态性

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

最佳答案

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

更新:

这是访问者模式的秘诀:

  1. 声明一个接口(interface):

    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 方法重命名为 访问)。

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

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

相关文章:

java - 在 junit 测试中模拟 DateFormat 类

java - Gradle:如何仅从项目的一部分创建库?

c++ - 内存泄漏和多态性

c++ - 为什么我们需要 C++ 中的虚函数?

java - 无法添加 OAuth 2.0 范围 LinkedIn

Java 1.6 java.sql try/catch/finally 疯狂编码

java - 在 Netbeans 中设置 4 个空格选项卡?

c++ - 家长访问 child 私有(private)/ protected

php - Laravel 5.1 - 多列的多态关系

java - 为什么重写的方法不表现出多态行为?