基本クラスがありBase
ます。2つのサブクラスとがSub1
ありSub2
ます。各サブクラスにはいくつかの追加メソッドがあります。たとえば、Sub1
has Sandwich makeASandwich(Ingredients... ingredients)
、およびSub2
has boolean contactAliens(Frequency onFrequency)
。
これらのメソッドは異なるパラメーターを取り、まったく異なることを行うため、完全に互換性がなく、この問題を解決するためにポリモーフィズムを使用することはできません。
Base
ほとんどの機能を提供し、Base
オブジェクトの大規模なコレクションを持っています。ただし、すべてのBase
オブジェクトはa Sub1
またはaのいずれかSub2
であり、時にはそれらがどれであるかを知る必要があります。
次のことを行うのは悪い考えのようです。
for (Base base : bases) {
if (base instanceof Sub1) {
((Sub1) base).makeASandwich(getRandomIngredients());
// ... etc.
} else { // must be Sub2
((Sub2) base).contactAliens(getFrequency());
// ... etc.
}
}
そこで、キャストせずにこれを回避する戦略を思いつきました。 Base
現在、これらのメソッドがあります:
boolean isSub1();
Sub1 asSub1();
Sub2 asSub2();
そしてもちろん、Sub1
これらのメソッドを次のように実装します
boolean isSub1() { return true; }
Sub1 asSub1(); { return this; }
Sub2 asSub2(); { throw new IllegalStateException(); }
そして、Sub2
それらを逆の方法で実装します。
残念ながら、現在Sub1
、Sub2
これらのメソッドは独自のAPIにあります。そのため、たとえばでこれを行うことができますSub1
。
/** no need to use this if object is known to be Sub1 */
@Deprecated
boolean isSub1() { return true; }
/** no need to use this if object is known to be Sub1 */
@Deprecated
Sub1 asSub1(); { return this; }
/** no need to use this if object is known to be Sub1 */
@Deprecated
Sub2 asSub2(); { throw new IllegalStateException(); }
このように、オブジェクトがaのみであることがわかっている場合Base
、これらのメソッドは非推奨ではなく、サブクラスのメソッドを呼び出すために別の型に「キャスト」するために使用できます。これはある意味ではエレガントに思えますが、一方で、クラスからメソッドを「削除」する方法としてDeprecatedアノテーションを悪用しています。
以来Sub1
インスタンスが本当にあるベース、それは使用の継承ではなく、カプセル化にメイクセンスを行います。私がやっていることは良いですか?この問題を解決するより良い方法はありますか?
instanceof
、多くの入力が必要で、エラーが発生しやすく、サブクラスを追加するのが難しくなります。
Sub1
、Sub2
なぜそれらをそのように扱うのですか?「サンドイッチメーカー」と「エイリアンコンタクター」を別々に追跡してみませんか?