3

プロジェクトでコードの重複を減らすためにいくつかのクラスを一般化するときにエラーが発生しました。その場合は次のとおりです。

interface ClassRoot{}

public class ClassChild1 implements ClassRoot{
    // constructor is omitted for simplicity
    public Collection<ClassChild1> createList(){

        Collection<ClassChild1> col = getCollectionFromSomewhere();
        return col;
    }
}

public class Class1{
    protected <T extends ClassRoot> Collection<T> doSth(){
        Collection<T> myCol = null;
        ClassChild1 child = new ClassChild1();

        // here I get compile time assignment error
        // also (assuming that myCol not null) myCol.add(new ClassChild1());
        // is not permitted.
        myCol = child.createList();
        return myCol;
    }
}

それはポリモーフィズム現象に反していませんか?たとえば、

List<Object> list1;

次のものには決してできません (また、型安全性のために割り当てるべきではありません):

List<String> list2;

しかし、ここでは私の場合は異なります.OOPポリモーフィズムの概念を利用することを期待して、特定のクラスを拡張するタイプパラメータを指定し、正しいクラスを正確に実装する割り当てを行いました. 2 つの質問があります。

  • 正当な理由で、Javaで禁止されている理由を誰かが明確に説明できますか?
  • 型パラメーターまたはワイルドカードを使用して、このような機能を実装するにはどうすればよいですか?
4

5 に答える 5

1

課題

Collection<T> myCol = null;
myCol = child.createList();

不明なタイプCollection<ClassChild1>のパラメータ化された に代入しているため、失敗します。CollectionTClassChild1

呼び出しサイトで推論されるように指定Tしたので、次のコードを想像してください。

Class1 c1;
Collection<ClassChild2> c = c1.doSth();

この例ではたまたま のインスタンスを保持しているコレクションにインスタンスをdoSth追加する必要があるため、このようなメソッドをコンパイルできるようにすると、コンパイラは自分自身をコーナーにペイントすることがわかります。ClassChild1ClassChild2

于 2012-08-01T08:45:47.343 に答える
0

createListコレクションを提供しません。これもエラーです。

ClassChild1のリストをのリストに割り当てることはできませんT

たとえば、名前を、、に変更したRootClass場合。の1つのインスタンスがではない場合、必要な割り当てを行うことはできません。AnimalClassChild1CatTCat

于 2012-08-01T09:03:15.117 に答える
0

問題が何であるかを判断するのは難しいです。理由は次のとおりです。

public ClassChild1 createList(){

間違っている必要があります(他の人が指摘しているように)。それは実際に言いますか:

public Collection<ClassChild1> createList(){

これは正常にコンパイルされます:

import java.util.*;

interface ClassRoot {}

class ClassChild1 implements ClassRoot {

    public Collection<? extends ClassRoot> createList(){

        Collection<ClassChild1> col = new ArrayList<ClassChild1>();
        return col;
    }
}

class Class1{
    protected Collection<? extends ClassRoot> doSth(){
        Collection<? extends ClassRoot> myCol = null;
        ClassChild1 child = new ClassChild1();

        myCol = child.createList();
        return myCol;
    }
}

createListに割り当て可能なものを返すことを宣言しましたClassRoot。それが返すものはそれと互換性があります。

その後doSth、同じものを返すように変更したので、互換性もあります。

欠点は、まだ電話をかけられないことです。

myCol.add(child);

そして、正当な理由で-コレクションアイテムにどのような制限があるかはわかりませんが、それは制限がないことを意味するわけではありません(ライトをオフにしても部屋は消えません)。

于 2012-08-01T09:04:17.590 に答える
0

あなたのコードをここに因数分解しました。あなたの ClassChild 実装は、

public class ClassChild implements ClassRoot {
    public List<ClassChild> createList() {
        return Arrays.asList(new ClassChild[] {new ClassChild(), new ClassChild()});
    }


}

あなたのClass1は

public class Class1 {

    public static <T extends ClassRoot> Collection<T> doSth(){
        Collection<T> myCol = null;
        ClassChild child = new ClassChild();
        /*you should note here*/
        myCol =  (Collection<T>) child.createList();
        return  myCol;
    }
}

「ここに注意する必要があります」と私が言った場所で停止する必要があります。Collection としてキャストすると、問題は解決します。しかし、あなたの質問に来て、ClassRoot を拡張する型 T を含む myCol という名前のコレクションを作成しました。しかし、 createList がサブタイプ ClassRoot を含むコレクションを返すという保証は何ですか? したがって、常に明示的にキャストする必要があります。

于 2012-08-01T09:36:08.480 に答える
0
Collection<ClassChild1> col = getCollectionFromSomewhere();
return col;

コレクションを返していますが、実際には ClassChild1 はコレクションではありません。これは間違いなくコンパイル時エラーを作成します。メソッドの戻り値の型がコレクション型またはその子孫でなければならないことを確認してください

于 2012-08-01T08:54:15.413 に答える