簡體   English   中英

Java抽象類用泛型實現接口

[英]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的子類型....

SubClassAMyClass<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;
    }

}

找到另一個解決方

  1. 在構成comaprable的字段上定義接口(例如ComparableFoo)
  2. 在父類上實現接口
  3. 在父類上實現Comparable。
  4. 寫下你的實現。

解決方案應如下所示:

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM