2017-05-27 12 views
3

私は大学のこのプロジェクトに取り組んでいます。私はここで何か間違っていると思います。私はJavaのサブクラス化とクラス継承を十分に理解していないと思います。スーパークラスのArrayListをとるコンストラクタにサブクラスのArrayListを渡しますか?

私はこの小さな形で私の問題を書き直しました。少しの言葉で

class SuperClass { 

     int dunno; 

     public SuperClass(int dunno) { 
      this.dunno = dunno; 
     } 
    } 

    class SubClass extends SuperClass { 

     int duncare; 

     public SubClass(int dunno, int duncare) { 
      super(dunno); 
      this.duncare = duncare; 
     } 
    } 

    class VeryBigClass { 

     ArrayList<SuperClass> superList; 

     public VeryBigClass(ArrayList<SuperClass> superList) { 
      this.superList = superList; 
     } 
    } 

    public void main(String[] args) { 

     new VeryBigClass(new ArrayList<SubClass>()); // this is the problematic line 

    } 

} 

私は1つの、より一般的なクラスを拡張するクラスの多くを書き、多くの場所で私の代わりに1でサブクラス1のそれぞれの治療のため、スーパークラス(一般的なもの)で業務を行っています同じやり方で。

しかし、私は必要なクラスのインスタンスを作成できません。コンストラクタは引数としてスーパークラスを取るためです。 new VeryBigClass(new (ArrayList<SuperClass>)ArrayList<SubClass>());は明らかに間違っているので、私はそれをキャストする方法も知らない。さらに、これらのインスタンスの構築は、ある時点でjsonライブラリによって処理されるので、私はむしろそのような面白いものをしたくないでしょう...

答えて

6

ジェネリックを使用する場合、それはうまく動作するはずですが、同じではありませんサブクラスのリストよりもスーパークラスのリストが、ジェネリックはこの問題を解決:

class VeryBigClass<T extends SuperClass> { 

    ArrayList<T> superList; 

    public VeryBigClass(ArrayList<T> superList) { 
     this.superList = superList; 
    } 
} 
+0

しかし、あなたは理由を説明しないでください! –

3

Javaチュートリアルは、この説明http://docs.oracle.com/javase/tutorial/java/generics/inheritance.html

ボトムラインでは、あなたがジェネリックとしてSub extends Superのように、継承関係を持つ型を持っている場合は、彼らはではない継承relatiを与えるそれらを保持するクラスのオンシップ:Foo<Sub>Foo<Super>のサブタイプではありません。

なぜなら、Liskov Substitutionの原則を破って、ジェネリックタイプに含まれるタイプの約束を破るからです。 List<Sub>List<Super>を延長した場合は、これを行うには、法的次のようになります。

List<Sub> subs = new ArrayList<Sub>(); 
List<Super> supers = subs; 

Super super = new Super(); 
supers.add(super); 

おっと!今度はsubsにはタイプSuperの要素があり、完全に違法です!

ArrayList<Sub>あなたは

new VeryBigClass(new ArrayList<SubClass>()); 

を起動したときに法的なかったコンストラクタに引数を渡され、List<Super>のサブタイプではないので。

2

また、ワイルドカード? extends superを使用することもできます。つまり、superを継承するすべてのクラスです。

class VeryBigClass { 

    ArrayList<? extends SuperClass> superList; 

    public VeryBigClass(ArrayList<? extends SuperClass> superList) { 
     this.superList = superList; 
    } 
} 
+0

宣言された型のワイルドカードはちょっと面倒です。メソッドの引数と戻り値の型には適しています。なぜなら、それらのフィード型は宣言の方が優れているからですが、変数型としては情報が少なすぎるからです。 'VeryBig'をジェネリッククラスにするために、先ほどのアドバイスに従う方が良いでしょう。 –

+0

ああ、誰かがこれを行うことができるか分からなかった!それは確かに、おかげで助けになる:) –

関連する問題