[英]Name Clash, override fail, on a class implementing two interfaces with same erasure
我正在創建一個覆蓋方法簽名的類,其擦除在兩個實現的接口之間是相同的,但在泛型類型方面有一些細微的差別(一個是方法推斷類型,另一個是推斷類類型)。 我正在尋找一個簡潔的解決方案。 我只能編輯繼承的類,而不是原始的遺留接口。
為了說明這個案例,我編寫了一個抽象樣本,以了解問題:
我有一個開發人員遺留父類:
public class Developer<C>{
Rate<C> getRate(Taxes<C> tax){ /*...*/ }
}
我還有一個Rentable傳統界面,簽名幾乎相同
public interface Rentable {
<C> Rate<C> getRate(Taxes<C> taxes);
}
由於開發人員不可出租,在我的模型中,我創建了一個特殊的開發人員,它既是Developer,也是Rentable材料。
public class OutsourcableDeveloper<C>
extends Developer<C>
implements Rentable{
@Override
public Rate<C> getRate(Taxes<C> taxes){ /*...*/}
}
然后我得到了臭名昭着的
名稱沖突:類型為OutsourcableDeveloper的方法getRate(Developer.Taxes)與類型為Rentable的getRate(Developer.Taxes)具有相同的擦除功能但不覆蓋它
我怎樣才能擺脫它,所以OutsourcableDeveloper.getRate()隱藏了Developer和Rentable。 的getRate()?
失敗一個普通的覆蓋似乎有點不合邏輯,但隨后刪除兩個簽名,因為刪除是相同的。
真的很重要的是,其中一個超類型推斷出來自de方法的類型,另一個來自類,特別是當我不打算在我的實現中調用任何超級時? 鑒於這種簡化,是否有一個技巧可以克服這個問題?
編輯:我打開了一個更抽象,更少解決方案面向我的實際問題,討論繼承設計問題的問題,我認為這是我遇到的實際問題的相關本質: 為什么我不能擴展接口“泛型方法“並將其類型縮小為我繼承的接口”class generic“?
編輯2:上一個問題引導我到這里發布的答案
那么他們實際上是不平等的。 因為任何Rentable-Instance允許給出任何類型參數T,而OutsourcableDeveloper限制它。
當然你可以假設在你的情況下很容易使用
<C> Rate<C> getRate(Taxes<C> taxes);
界面版本。 但是如果他想要將OutsourceableDeveloper
子類化,那么預計開發人員會有多么困惑。 根據Developer的定義,他可以假設Method getRate固定為C
但實際上它可以突然取任何值。 - >允許這會導致混亂。
我能為您提供的是以下代碼示例,它可能適合您的情況。 雖然使用它肯定會不方便。 但是當您將所有方法轉發到OursourcableDeveloperRentable時,它是可能的。 評論應該解釋它是如何工作的。
//This class itself can be added to any Developer-lists
public class OutsourcableDeveloper<C> extends Developer<C> {
public final OutSourcableDeveloperRentable RENTABLE_INSTANCE = new OutSourcableDeveloperRentable();
@Override
public Rate<C> getRate(final Taxes<C> taxes) {
// Simply forward to the more general getRate instance.
return this.RENTABLE_INSTANCE.getRate(taxes);
}
public void exampleBehaviourA() {
//Example for how you can make both objects behave equally.
}
// This class can be added to the lists requiring a Rentable
// And the original value can be retrieved by both classes.
public class OutSourcableDeveloperRentable implements Rentable {
public final OutsourcableDeveloper<C> PARENT_INSTANCE = OutsourcableDeveloper.this;
//This method is the one to implement because it is more general than
//the version of OutsourcableDeveloper.
@Override
public <T> Rate<T> getRate(final Taxes<T> taxes) {
// Do your work.
return null;
}
public void exampleBehaviourA() {
//Just an example - Maybe for you it makes for sence to
//forward the method of Oursoursable-Developer to here.
//Then all Behaviour would be found in this class.
OutsourcableDeveloper.this.exampleBehaviourA();
}
}
}
好的,我找到了解決問題的方法。 它是塊狀的,但如果架構不是很復雜,那么它就更容易了,受到我的啟發為什么我不能擴展接口“泛型方法”並將其類型縮小到我繼承的接口“class generic”? 自己的答案:
public class OutsourcableDeveloper<C>
extends Developer<C>
implements Rentable{
/* This might not be needed if we don't need to extract C from taxes parameter */
final Class<C> currencyClass;
public OutsourcableDeveloper(Class<C> currencyClass){ this.currencyClass = currencyClass;}
@Override
public Rate<C> getRate(@SuppressWarnings("rawtypes") Taxes taxes){
try{
C taxesCurrency = (C) currencyClass.cast(taxes.getCurrency()); //IF actually needed getting the typed instance
return new Rate<C>(taxesCurrency); //Or whatever processing
} catch (ClassCastException e){
throw new UnsupportedOperationException("OutsourcableDeveloper does not accept taxes in a currency that its not hims");
}
}
}
也可以使用“extends Developer”而不使用泛型類型,因此它顯然是原始的。 但我們也為非沖突方法打字
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.