サブタイプの「オーバーライド」インスタンス変数:可能なリスク?
-
30-09-2019 - |
質問
スーパークラスから継承するクラスのスーパークラスと2つのサブクラスサブクラスとサブクラスブがあったとします。
abstract class SuperClass{
...
List someList;
...
}
class SubClassA extends SuperClass{
...
List<String> someList;
...
}
class SubClassB extends SuperClass{
...
List<Integer> someList;
...
}
そうすれば、私は手に入れることができるので便利です someList.size()
の Superclass
サブクラスにタイプフェティがあります。問題は、それが正しく「感じ」ないということです。あなたは私が知らないこのApporachが持っている潜在的な危険を考えることができますか?
解決
一つには、任意の方法 SuperClass
サブクラスのリストではなく、スーパークラスリストを見る。これはほぼ確実に微妙なバグにつながります。たとえば、あなたが言うとき
私は得ることができます
someList.size()
のSuperclass
あなたが実際に得るのは、のリストのサイズです Superclass
, 、サブクラスのものではありません。サブクラスリストには要素(またはその逆)が含まれている間、スーパークラスリストは空になる場合があります。
この背後にある理由はそれです SubClassA.someList
決して交換またはオーバーライドすることはありません Superclass.someList
- それはただそれを影にするので、サブクラスの方法は SubClassA.someList
それ以外の Superclass.someList
. 。ただし、これはまったく効果がありません Superclass
. 。メソッドは仮想にすることができます(そしてJavaではデフォルトでは)が、データメンバーはできません。
他のヒント
これは本当に悪い考えです。あなたは 本当 いずれかのサブクラスのインスタンスが必要です 2 リスト?それが起こっていることだからです。 2番目の変数を宣言しているため、スーパークラスのコードは1つの変数を使用し、サブクラスのコードは別の変数を使用します。それはただトラブルを求めている、IMO。
クラスメンバー変数の代わりにメソッドを定義する必要があると思います。サブクラスにメソッドを実装できるようになり、タイプの安全性について心配する必要はありません。
私が提案する方法に変数を置き換えます。
ありがとう。
私にはIS-Aとリスコフの代替原則を破っているようです。スーパークラスインスタンスのコレクションがある場合、それぞれがサブクラッサまたはサブクラスブである可能性がある場合、せいぜい驚くべき振る舞いが得られます。
それをしないでください。
たぶん、ジェネリックを使用する方が良いでしょう:
public class X<T>
{
private List<T> list;
}