2012-04-11 4 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()メソッドを開始するはずです。問題は、オブジェクトがWidgetAなどではなく、Widgetオブジェクトとして扱われることです。instanceofを使用して型をループすることができますが、私はその使用を避けようとしています。 process()メソッドのロジックは、Fooクラスのプライベートフィールドにアクセスする必要があるため、それらをWidgetサブクラスに移動することは最適ではないかもしれません。

問題は、instanceofを使用せずに、特定のWidgetサブタイプに対して正しいprocess()メソッドを呼び出す方法があるかどうかです。

+0

[instanceof]オペレータのこの使用は悪い設計を考慮していますか?](http://stackoverflow.com/questions/8841577/is-this-use-of-the-instanceof-operator-considered-悪いデザイン) –

答えて

3

はい、ダブルディスパッチとも呼ばれるVisitorパターンをご覧ください。

0

もう1つの潜在的な解決策は、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()方法を定義しているために持っているか、例外が実行時にスローされるということで。実装が不足している場合、コンパイラは警告しません。

関連する問題