2

これが私がやろうとしていることのようなものです:

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() メソッドを開始して、渡されたインデックスでオブジェクトを処理することになっています。問題は、オブジェクトが WidgetA などではなく Widget オブジェクトとして扱われることです。instanceof を使用して型をループすることもできますが、それを使用しないようにしています。process() メソッドのロジックは Foo クラスのプライベート フィールドにアクセスする必要があるため、それらを Widget サブクラスに移動するのは最善の方法ではない可能性があります。

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

4

2 に答える 2

3

はい、Visitor パターン (ダブル ディスパッチとも呼ばれます) を見てください。

于 2012-04-11T19:06:12.367 に答える
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と、実行時に例外がスローされます。実装が欠落している場合、コンパイラは警告しません。

于 2012-04-11T19:35:50.740 に答える