5

もともと、スーパークラスの5つのサブクラスが必要な設計上の問題があり、2つを除くすべてが同じ一般的な方法で処理を行い、他の2つのクラスは特別な処理が必要でした。メソッドを5回書くのは避けたかったのです。2つの特殊なケースと3つの同一のケース。

そのため、すべてのクラスにSuperClassとそのdoSomething()メソッドを継承させ、SubClassSpecial1とSubClassSpecial2を独自のdoSomeThingメソッドでオーバーライドさせました。

次のようなメソッドを作成するまでは、これで問題ありませんでした。

void fooBar(SuperClass obj) {
    obj.doSomething()
}

そしてそれは次のように呼ぶことができますfooBar( new SubClassSpecial1() );

問題は、obj変数のランタイムクラスがそのスーパークラスのランタイムクラスになり、スーパークラスで定義されたメソッドを呼び出すことです。もちろん、スーパークラスで抽象doSometing()メソッドを作成し、各サブクラスに独自のバージョンを実装させることもできますが、それでは3つのクラスのコードが重複します。そして、私はそれを避けたいです...

たくさんの分岐があった場合、ポリモーフィズムが与えるゲインは失われます

if(obj.getClass().getName() == "SubClassSpecial1" )  ((SubClassSpecial1) obj).doSomething()K;
else if ...

では、デザインをよりエレガントでハックのないものにするために、私は何をすべきでしょうか?

4

3 に答える 3

5

私はあなたの質問のこの部分に少し混乱しています:

もちろん、私がやりたかったのは、各オブジェクトに独自のバージョンのdoSomething()を呼び出させることでしたが、それを行うには、objをサブクラス化されたメソッドの1つとして宣言する必要があることに気づきませんでした。そして今、それは混乱です。

もちろん、宣言は重要ではありません。doSomething()メソッドは、クラスの実行時型に従って常に呼び出されます。

ですから、あなたがやろうとしていたことはうまくいくはずだと思います。たとえば、これらの宣言はすべてfoobarメソッドに渡すために使用できます。

SuperClass sc1 = new SubClassSpecial1();
SubClassSpecial2 sc2 = new SubClassSpecial2();
//etc..
于 2009-11-02T14:42:21.407 に答える
2

あなたが説明したことはそのままでうまくいくはずです。

obj.doSomething()は実際にスーパークラスの実装を呼び出していますか?そうである場合、それを適切にオーバーライドしていません。オーバーライドされたバージョンの署名が変更されていないことを確認してください。

于 2009-11-02T14:50:36.217 に答える
1

あなたがこれを持っているとき:

void fooBar(SuperClass obj) {
    obj.doSomething();
}

その場合、のコンパイル時タイプはobjですSuperClass。これは、コンパイラがメソッドをSuperClass持っているかどうかをチェックすることを意味しdoSomething()ます。実行時
に、のサブクラスを置き換えることができます。これは、リスコフの置換原則です。メソッドは、ランタイムタイプが何であるかを知らないため、知る必要はありません。メソッドが派生しているため、呼び出すことができます。 SuperClassfoobar()objSuperClassdoSomething()

あなたの例に関して:

fooBar( new SubClassSpecial1() );

この場合、パラメータのランタイムSubClassSpecial1タイプが具体的にをオーバーライドするものであることがわかりますdoSomething()すべての場合において、正しいメソッドが呼び出されます。

リファクタリングについて一言。階層のリファクタリングを検討することをお勧めします。
基本クラスは抽象としてSuperClass定義する必要があります。doSomething()同じ実装を必要とする3つのクラスdoSomething()は、その特定の実装を持つ中間基本クラスから継承する必要があります。2つの特別なクラスは、から直接継承しSuperClass、独自の実装を持つ必要がありdoSomething()ます。

于 2009-11-03T23:24:05.347 に答える