【问题标题】:Downcasting and polymorphism without using instanceof? (Java)不使用instanceof的向下转换和多态? (爪哇)
【发布时间】:2012-04-11 19:04:23
【问题描述】:

这是我正在尝试做的事情:

class Foo {
    private ArrayList<Widget> things; //Contains WidgetA, WidgetB and WidgetAB objects
    //...
    void process(int wIndex) {
       process(things.get(wIndex);
    }

    private void process(WidgetA w) {
       //Do things
    }
    private void process(WidgetB w) {
       //Do other things
    }
    private void process(WidgetAB w) {
       //Do completely different things
    }
}

abstract class Widget {
    //...
}

class WidgetA extends Widget {
    //...
}
class WidgetB extends Widget {
}
class WidgetAB extends WidgetA {
}

基本上,一个单独的类从用户输入中获取一个数组索引,并将其传递给 process(int) 方法,该方法应该启动一个特定于类型的 process() 方法来处理传递索引处的对象。问题是这些对象被视为 Widget 对象,而不是 WidgetA 等。我猜我可以使用 instanceof 遍历类型,但我试图避免使用它。 process() 方法中的逻辑需要访问 Foo 类中的私有字段,因此将它们移至 Widget 子类可能不是最好的主意。

所以问题是,有没有一种方法可以为给定的 Widget 子类型调用正确的 process() 方法,而不使用 instanceof?

【问题讨论】:

标签: java polymorphism


【解决方案1】:

是的,看看访问者模式 - 也称为双重调度。

【讨论】:

    【解决方案2】:

    另一个可能的解决方案是使用 Java 的反射 API。示例:

    class Foo {
        private ArrayList<Widget> things; //Contains WidgetA, WidgetB and WidgetAB objects
        //...
        void process(int wIndex) {
            Widget theWidget = things.get(wIndex);
            try {
                Class type = theWidget.getClass();
                Class[] arg_types = new Class[]{type};
                this.getMethod("process", arg_types).invoke(this, theWidget);
            } catch (Exception e) {
                //Could be SecurityException or NoSuchMethodException
            }
        }
    
        private void process(WidgetA w) {
           //Do things
        }
        private void process(WidgetB w) {
           //Do other things
        }
        private void process(WidgetAB w) {
           //Do completely different things
        }
    }
    
    abstract class Widget {
        //...
    }
    
    class WidgetA extends Widget {
        //...
    }
    class WidgetB extends Widget {
    }
    class WidgetAB extends WidgetA {
    }
    

    这里的问题是您必须为things 列表中的每种类型的对象定义一个process() 方法,否则将在运行时引发异常。如果您缺少实现,编译器不会警告您。

    【讨论】:

      猜你喜欢
      • 2011-06-24
      • 1970-01-01
      • 2016-02-16
      • 2012-12-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多