2012-04-11 39 views
2

下面是諸如此類的事情,我想要做的事:不使用instanceof向下轉換和多態性? (JAVA)

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

基本上,一個單獨的類會從用戶輸入數組索引,並將其傳遞到過程(int)方法,這是應該啓動一個特定於類型的process()方法來處理傳入索引處的對象。問題是,對象被視爲Widget對象,而不是WidgetA等。我可以通過使用instanceof來循環類型,我猜,但我試圖避免使用它。 process()方法中的邏輯需要訪問Foo類中的私有字段,因此將它們移動到Widget子類可能不是最好的主意。

所以現在的問題是,是否有正確的處理()方法的方式調用特定小亞型,而無需使用的instanceof?

+0

的可能重複[這是利用認爲是不好的設計了「的instanceof」操作的?](http://stackoverflow.com/questions/8841577/is-this-use-of-the-instanceof-operator-considered-糟糕的設計) – 2012-04-11 19:09:17

回答

3

是的,看看訪問者模式 - 也被稱爲雙調度。

0

另一個潛在的解決方案是使用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 { 
} 

這裏的問題是,你必須定義了process()方法在things列表中的每個類型的對象或異常會在運行時被拋出。如果缺少實現,編譯器不會警告您。