4

現在、スーパークラスをパラメーターとして使用して関数を実装しています。

例えば:

private void foo(Parent parent) {
    if(parent.getClass() == Child1.class) {
        Child1 c1 = (Child1) parent;
        System.out.println(c1.getChild1Attribute());
    }
    else if(parent.getClass() == Child2.class) {
        Child2 c2 = (Child2) parent;
        System.out.println(c1.getChild2Attribute());
    }
    else if(parent.getClass() == Parent.class) {
        System.out.println(parent.getParentAttribute());
    }
}

これは悪い考えですか?

getClass()ここでorを使用するのinstanceofは悪いデザインだと言っているスレッドをいくつか読みました:

4

5 に答える 5

7

これは必ずしも設計が悪いわけではありませんが、何か問題が発生している可能性があることを示しています。

単一のメソッドが複数のクラスを認識しているように見えるため、特定のケースは悪く見えます。これは、オーバーロードの可能性を見逃していること、または複数のディスパッチ パターンのいずれかを使用する機会を逃していることを示している可能性があります。

// Three overloads - one per target class
private void foo(Parent obj) {
}
private void foo(Child1 obj) {
}
private void foo(Child2 obj) {
}

一般的な複数ディスパッチ パターンの 1 つは訪問者パターンです。解決しようとしている問題に適用できるかどうかを確認してください。

于 2013-04-23T13:51:17.340 に答える
6

はい、設計が悪いです。

代わりに、スーパークラスで単一の抽象メソッドを作成し、それを各サブクラスでオーバーライドして、目的のアクションを実行する必要があります。

于 2013-04-23T13:50:45.870 に答える
2

はい、これは悪い設計の兆候です。これにより、関連する知識を適切なクラス自体にカプセル化するのではなく、さまざまなクラスを単一のクラスで処理するという複雑さが生じます。階層にさらにクラスを追加すると、コンパイラは関連する新しい機能を実装するように通知しないため、これは問題になりますfoo

より良いバージョンは

private void foo(Parent parent){
    System.out.println(parent.getFooParentAttribute());
}

getFooParentAttribute次に、各クラスに実装します。

于 2013-04-23T13:52:41.037 に答える
1

instanceofアプローチを好む

Josh Bloch によるデザイン

私が instanceof アプローチを好む理由は、getClass アプローチを使用すると、オブジェクトが同じクラス、同じランタイム タイプの他のオブジェクトとのみ等しいという制限があるためです。

于 2013-04-23T13:52:38.113 に答える
0

そのままの方法には2つの問題があります。まず、 の新しいサブクラスを追加するとしParentますChild3。これはどのケースでもカバーされていないため、何も出力されません。の新しいサブクラスを追加した場合も同様Child1ですChildOfChild1。それも対象になりません。

instanceof代わりに使用していた場合、 thenChildOfChild1は のインスタンスとして表示され、 は のインスタンスにChild1なりChild3ますParent

しかし、一般的に、このパターンを完全に回避したい理由は、これらすべてのケースが驚くべきものになる可能性があるためです。一般的に良いのは、書くことです

void foo(Parent p) {...}

そこに一般的なコードを入れて、特別な場合のために、

void foo(Child1 c) {...}

これにより、何が起こっているのかが明確になります。これら 2 つのメソッドChild1(およびそのサブクラス) には特別なケース コードが含まれていることがわかりますがParent、その他のサブクラスはすべて同じように扱われます。

于 2013-04-23T13:58:05.783 に答える