簡體   English   中英

名稱沖突,覆蓋失敗,在實現具有相同擦除的兩個接口的類上

[英]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.

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