2016-07-24 168 views
-1

的子類我有這個類:如何返回泛型類型

public abstract class Parent {} 
public class Child extends Parent{} 

我做出了一流的連接器,我想的是T類將承擔母公司的子類:

public class Connector <T extends Parent>{ 
    T t; 
    public Connector(T t){ 
     this.t=t; 
    } 
    public T getObject(T t){ 
     Child p = new Child(); 
     return (T) p;  
    } 
} 

實現:

Child c1 = new Child(); 
Connector<Parent> cConnector = new Connector<Parent>(c1); 
Child c2 = cConnector.getObject(c1); 

一切與演員合作,但我不明白爲什麼我必須添加一個演員到什麼是ret如果T延伸,請在getObject方法中使用父

+3

考慮'公共類Child2 extends Parent {}'。你的代碼中斷了一個'ClassCastException'。問題是:你想在這裏做什麼?爲什麼'getObject'將'T'作爲參數? – Tunaki

+0

@tunaki getObject將T作爲參數,因爲我想對父類 – joumvaer92

+0

@ joumvaer92的子類進行操作如果您在操作它之後只是簡單地返回't',那麼您可以這樣做,但是您不能假設't ''將始終是'Child'類型,所以這就是爲什麼你需要一個強制類型來返回一個'Child'類型的對象,但是我會考慮在構造'Connector'時返回't'並使'tt'類型爲'Child' ' –

回答

0

Connector中介紹的本地Child p變量和泛型T之間沒有任何關聯。 getObject方法中既沒有使用字段T t也沒有使用參數T t,因此需要明確的cat。

如果您提供以下getObject實現:

public T getObject(){ 
    return t;  
} 

沒有必要對投了。

0

問題是TChild類沒有連接。請叫Pet擴展Parent另一個類,

public class Pet extends Parent{ 
    ... 
} 

現在讓我們重新您getObject方法。與Pet替換T的實例,

在主,我們現在有

Pet p = new Pet(); 
Connector<Pet> cConnector = new Connector<Pet>(p); 

在連接器類,

//** symbol is used as placeholder, not actually part of the code 
public *Pet* getObject(*Pet* t){ 
    Child p = new Child(); 
    return (*Pet*) p;  
} 

爲什麼需要投的原因是沒有保證PetChild有關係。如果省略了投射,則當返回類型爲Pet時,將返回類型爲Child的對象,這會導致錯誤,因爲Pet不等於Child。如果你想返回Child類型的新的對象,然後我會建議做這樣的事情(參數可以因爲你以前沒有使用它可以省略),

public Child getObject(){ 
    Child p = new Child(); 
    return p; 
} 

public Child getObject(T t){ 
    //do operations on t here 
    return t; 
} 
0

getObject方法中,當結果應該是Parent的任何子項時,您創建Child的實例。如果您嘗試將其與任何其他類型一起使用,則此代碼將中斷AnotherChild extends Parent

解決此問題的辦法是爲子對象傳遞工廠方法。

public class Connector <T extends Parent>{ 
    Supplier<T> factory; 
    T t; 
    public Connector(T t, Supplier<T> factory){ 
     this.t=t; 
     this.factory = factory; 
    } 
    public T getObject(T t){ 
     return factory.get(); 
    } 
} 

然後使用看起來像

Child someChild = new Child(); 
Connector<Child> connector = new Connector<>(someChild, Child::new); 
0

你說的「一切跟投工作」,當然,它的工作原理,但它是容易出錯的,順便說一句的意思是什麼,你用泛型類型,錯誤的方式。

當你寫:

<T extends Parent> 

這意味着你的類可以接受所有的類型T是母公司的一個子類。使其更清楚,看到這樣的代碼:由於你的類定義

public class FruitBaskets<T extends Fruit>{ 
T t; 
public addFruit(T t){ 
    this.t=t; 
} 
public T getFruit(T t){ 
    return t;  
    } 
} 

FruitBasket<Apple> myFuitBasket = new FruitBasket(); 

,你說得很清楚,你接受來自水果擴展類型,所以不`噸需要擔心約OBJ添加或從中檢索你的水果籃(不需要投射),如果有人試圖給你的水果籃添加一隻狗,他會得到一個編譯時異常,你可以捕獲並修復它,並防止運行時異常。