2013-08-23 80 views
8

我必須確保對象可以使自己的副本界面:子類繼承通用接口

public interface Duplicable<T extends Duplicable<T>> { 
    public T duplicate(); 
} 

我現在有

class X implements Duplicable<X> 

,但我也有一個擴展X.

一個Y級

這是不是一個問題,直到我需要另一個通用類:

public class DoStuffWithDuplicable<T extends Duplicable<T>> 

我不能使用通過ÿDoStuffWithDuplicable的通用版本,因爲它沒有實現Duplicable<Y>Duplicable<X>,因爲它繼承了來自十

所以,我想

public class DoStuffWithDuplicable<T extends Duplicable<? super T>> 

..但是,這意味着稍後引入不安全的鑄造

(T) obj.duplicate() 

在代碼正文中。此外,班級參數更復雜,班級的使用更難理解。任何想法如何解決這個問題?

+0

你能改寫這個:「我不能使用通過ÿDoStuffWithDuplicable的通用版本,因爲它由於它從X繼承它,因此不實現可複製但可複製的。「 ? – tbsalling

+0

對不起,格式化問題 – phil

+1

請注意,這正是一些計算機科學家說所有類都應該是「抽象」或「最終」的原因。你也會碰到'equals'的問題;你可能重構消除一個可實例化的'X'? – chrylis

回答

1

我可能沒有正確理解你的問題,但我會給它一個。

首先,爲什麼你有一個像這樣擴展自己的接口?

什麼,你可以嘗試是這樣的:

public interface Duplicable<T> { 
    public T duplicate(); 
} 

然後,當您使用您希望泛型參數要複製的另一個類,你做這樣的:

public class X<T extends Duplicable<T>> { 
    code... 
} 

現在,當你從X繼承,子類中的任何通用組件都必須是可複製的。

+1

我認爲「爲什麼」很明顯:OP想要將'T'約束爲與實現它的類相同的類型。你的方式允許,例如'Integer'來實現'Duplicable '。 –

+0

@MarkoTopolnik:1)但是OP的約束並沒有限制它。限制它是不可能的。 2)無論如何,OP的約束條件並不具有任何類型安全性。該接口是安全的,因爲它是。 – newacct

+0

與'Enum'約束其類型參數相同的方式''T extends Duplicable >'約束'T':'Enum >'。 'E'必須是枚舉類本身。 –

1

在Java中無法做到這一點。

假設您在類型Y的對象上調用obj.duplicate()。然後類型系統只能確保它將返回類型X的對象,因爲Y實現重複<X>。

但是,您可以創建一個DoStuffWithDuplicable <X>並將Y對象傳遞給它。

DoStuffWithDuplicable<X> blub = new DoStuffWithDuplicable<X>(); 
    Y y = (Y) blub.doStuff(new Y()); 

對於返回值,你的庫的客戶端可以只使用安全的強制類型轉換,因爲他可能知道具體類型。

的另一個選項是在圖書館使用不安全的類型轉換和手動檢查類型:

class DoStuffWithDuplicable<T extends Duplicable<? super T>> { 
    T doStuff(T obj) { 
     @SuppressWarnings("unchecked") 
     T t = (T) obj.duplicate(); 
     if (!t.getClass().equals(obj.getClass())) 
      throw new ClassCastException("..."); 
     return t; 
    } 
}