2013-08-16 18 views
4

我有以下類別:Java的泛型類可轉讓

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結合第一參數資源(同預期),而第二參數綁定到:

Wrap<ConcreteModel> 

應結合:

Wrap<? extends ModelObject> 

作爲ConcreteModel實現它。

+0

這是發生在Eclipse或JDK? Eclipse編譯器包含一些錯誤。 – gparyani

+2

@dsmog正確的術語是「泛型」(Java),「模板類」(語法上類似,但概念上在C++中概念上非常不同)。 –

回答

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>>(); 
    } 
} 

不編譯任。您的問題是SomeGeneric<Wrap<ConcreteModel>> is not a SomeGeneric<Wrap<? extends ModelObject>>

+0

+1爲噪聲切除術 – Bohemian

0

A Wrap<ConcreteModel>可以分配給Wrap<? extends ModelObject>類型的變量。但這裏的問題更爲複雜。假設你有一個ArrayList<Wrap<? extends ModelObject>> list。如果您有這種類型,則表示您可以將Wrap<ConcreteModel>添加到列表中,但這也意味着您可以向其添加Wrap<ModelObject>。簡而言之,這意味着你有一個列表,它可以包含任何可以投射到ModelObject的任何東西。

在另一邊,有一個ArrayList<Wrap<ConcreteModel>> list意味着你只能添加Wrap<ConcreteModel> s到它,而Wrap<ModelObject>不能被添加到它,因爲列表中只能包含包裹ConcreteModel S和包裹ModelObject不是包裹ConcreteModel它也不能被塑造成一個。

這正是你的情況。您宣佈您的createMapper()方法返回Transformer<Resource, Wrap<? extends ModelObject>>。這意味着返回的Transformer的第二個參數必須能夠是ModelObject的任何子類,包括ModelObject本身。相反,您試圖返回Transformer<Resource, Wrap<ConcreteModel>>

編譯器需要執行這一點,因爲Transformer<F, T>可以聲明的方法:

void myMethod(F fObject, T tObject); 

如果是這樣的情況下,Transformer<Resource, Wrap<? extends ModelObject>>類型的對象的方法myMethod將接受ModelObject類型的對象作爲第二個參數。另一方面,在Transformer<Resource, Wrap<ConcreteModel>>類型的對象中,同樣的方法不能接受作爲其第二個參數

1

Wrap<ConcreteModel>Wrap<? extends ModelObject>的子類型?是。

Transformer<Resource, Wrap<ConcreteModel>>Transformer<Resource, Wrap<? extends ModelObject>>的子類型?沒有。

這是一樣的:

StringObject子類型?是。

List<String>List<Object>的子類型?基本上,爲了使參數化類型兼容,如果頂級參數不是通配符,那麼參數必須匹配,正好是。在你的情況下,頂層參數不是通配符,並且參數不完全匹配。

你可能想要的東西,而不是爲

Transformer<Resource, ? extends Wrap<? extends ModelObject>>