4

私は次のクラスを持っています:

    public interface ModelObject {
    }
    public interface Resource {
    }
    public interface Transformer <F,T>{
    }
    public interface WrapperFactory {
        Transformer<Resource, Wrap<? extends ModelObject>> createMapper();
    }
    public class Wrap<E extends ModelObject> {

    }

    public class AbstractBaseTransformer<F,T> implements Transformer<F,T> {
    }
    public class ConcreteModel implements ModelObject {

    }
    public class ConcreteTransformer extends AbstractBaseTransformer<Resource, Wrap<ConcreteModel>> {

    }
    public class ConcreteFactory implements WrapperFactory {

        @Override
        public Transformer<Resource, Wrap<? extends ModelObject>> createMapper() {
            return new ConcreteTransformer();
        }
    }

ConcreteFactory は、ConcreteTransformer が返されたものと互換性がないことを示すコンパイルを行いません。

Transformer<Resource, Wrap<? extends ModelObject>>

ここで何が問題なのかわかりません。ConcreteTransformer は、1 番目のパラメーターを Resource にバインドし (予想どおり)、2 番目のパラメーターを次のようにバインドします。

Wrap<ConcreteModel>

以下にバインドする必要があります。

Wrap<? extends ModelObject> 

ConcreteModel がそれを実装しているためです。

4

3 に答える 3

4

問題を絞り込むためのより単純なバージョンを次に示します。

interface ModelObject {}
class ConcreteModel implements ModelObject {}

class Wrap<E extends ModelObject> {}
class SomeGeneric<T> {}

class Simple {
    public SomeGeneric<Wrap<? extends ModelObject>> m() {
        return new SomeGeneric<Wrap<ConcreteModel>>();
    }
}

どちらもコンパイルしません。

あなたの問題は、 aが aSomeGeneric<Wrap<ConcreteModel>>ではないことSomeGeneric<Wrap<? extends ModelObject>>です。

于 2013-08-16T22:38:21.327 に答える
0

AWrap<ConcreteModel>は 型の変数に割り当てることができますWrap<? extends ModelObject>。しかし、ここでの問題はもっと複雑です。

あなたが持っていると仮定しますArrayList<Wrap<? extends ModelObject>> list。このようなタイプがある場合Wrap<ConcreteModel>、リストに a を追加できるという意味ですが、a を追加できるという意味もありますWrap<ModelObject>。簡単に言えば、にキャストできるもののラップを含むことができるリストがあることを意味しますModelObject

一方、リストにはラップされた sのみを含めることができ、ラップされた a はラップされておらず、1 にキャストすることもできないため、a をArrayList<Wrap<ConcreteModel>> list追加することはできませんがWrap<ConcreteModel>、aを追加することはできません。Wrap<ModelObject>ConcreteModelModelObjectConcreteModel

これはまさにあなたの場合です。createMapper()を返すようにメソッドを宣言しましたTransformer<Resource, Wrap<? extends ModelObject>>。つまり、返される Transformer の 2 番目の引数は、それ自体ModelObjectを含め、の任意のサブクラスにすることができなければなりませんModelObject。逆に、 を返そうとしていTransformer<Resource, Wrap<ConcreteModel>>ます。

Transformer<F, T>メソッドを宣言できるため、コンパイラはこれを強制する必要があります。

void myMethod(F fObject, T tObject);

その場合、myMethod型のオブジェクトのメソッドは、型のオブジェクトを2 番目の引数としてTransformer<Resource, Wrap<? extends ModelObject>>受け入れます。ModelObject一方、型のオブジェクト内の同じメソッドは、2 番目の引数としてa を受け入れるTransformer<Resource, Wrap<ConcreteModel>> ことができません。ModelObject

于 2013-08-16T23:27:03.207 に答える