[英]Java Abstract Class Implementing an Interface with Generics
我正在嘗試定義一個實現Comparable的抽象類。 當我使用以下定義定義類時:
public abstract class MyClass implements Comparable <MyClass>
子類必須實現compareTo(MyClass object)
。 相反,我希望每個子類都實現compareTo(SubClass object)
,接受自己類型的對象。 當我嘗試使用以下內容定義抽象類時:
public abstract class MyClass implements Comparable <? extends MyClass>
它抱怨說“超類型可能沒有指定任何通配符”。
有解決方案嗎?
在我看來,它有點過於冗長,但有效:
public abstract class MyClass<T extends MyClass<T>> implements Comparable<T> {
}
public class SubClass extends MyClass<SubClass> {
@Override
public int compareTo(SubClass o) {
// TODO Auto-generated method stub
return 0;
}
}
除了你在宣布簽名時遇到的機械困難之外,目標沒有多大意義。 您正在嘗試建立一個協變比較函數,它打破了建立派生類可以定制的接口的整個想法。
如果定義一些子類SubClass
使其實例只能與其他SubClass
實例進行比較,那么SubClass
如何滿足MyClass
定義的契約? 回想一下, MyClass
說它和從它派生的任何類型都可以與其他MyClass
實例進行比較。 你試圖讓SubClass
不成立,這意味着SubClass
不滿足MyClass
的契約:你不能用SubClass
代替MyClass
,因為SubClass
的要求更嚴格。
這個問題集中在協方差和逆變,以及它們如何允許函數簽名通過類型派生來改變。 您可以放寬對參數類型的要求 - 接受比超類型的簽名要求更寬泛的類型 - 並且您可以強化對返回類型的要求 - 承諾返回比超類型簽名更窄的類型。 這些自由中的每一個仍然允許完全替換派生類型的超類型; 當通過超類型的接口使用派生類型時,調用者無法區分,但是具體使用派生類型的調用者可以利用這些自由。
Willi的回答講述了關於泛型聲明的一些內容,但我建議您在以語義為代價接受該技術之前重新考慮您的目標。
看看Java自己的例子:
public abstract class Enum<E extends Enum<E>> implements Comparable<E>
public final int compareTo(E o)
關於seh的評論:通常論證是正確的。 但泛型使類型關系更復雜。 在Willi的解決方案中,SubClass可能不是MyClass的子類型....
SubClassA
是MyClass<SubClassA>
的子類型,但不是MyClass<SubClassB>
的子類型
type MyClass<X>
定義compareTo(X)
的契約,其所有子類都必須遵守。 那里沒有問題。
public abstract class MyClass<T> implements Comparable<T> {
}
public class SubClass extends MyClass<SubClass> {
@Override
public int compareTo(SubClass o) {
// TODO Auto-generated method stub
return 0;
}
}
找到另一個解決方
解決方案應如下所示:
public abstract class MyClass implements ComparableFoo,Comparable<ComparableFoo> {
public int compareTo(ComparableFoo o) {
// your implementation
}
}
這個解決方案意味着更多的東西可能會實現ComparableFoo - 這可能不是這種情況,但隨后你編寫了一個接口並且泛型表達式很簡單。
我不確定你需要捕獲:
首先,將compareTo添加到抽象類......
public abstract class MyClass implements Comparable <MyClass> {
@Override
public int compareTo(MyClass c) {
...
}
}
然后添加實現......
public class MyClass1 extends MyClass {
...
}
public class MyClass2 extends MyClass {
...
}
調用compare將調用超類型方法...
MyClass1 c1 = new MyClass1();
MyClass2 c2 = new MyClass2();
c1.compareTo(c2);
我知道你說你想要“compareTo(SubClass對象),接受一個自己類型的對象”,但我仍然建議像這樣聲明抽象類:
public abstract class MyClass implements Comparable <Object>
並在MySubClass中覆蓋compareTo時執行instanceof檢查:
@Override
public int compareTo(Object o) {
if (o instanceof MySubClass)) {
...
}
else throw new IllegalArgumentException(...)
}
類似'等於'或'克隆'
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.