名称冲突,覆盖失败,在实现具有相同擦除的两个接口的类上

时间:2015-12-12 17:37:55

标签: java generics inheritance polymorphism multiple-inheritance

我正在创建一个覆盖方法签名的类,该方法签名的擦除在两个实现的接口之间是相同的,但在泛型类型方面存在细微差别(一个是方法推断类型,另一个是推断类类型) 。我正在寻找一个简洁的解决方案。我只能编辑继承的类,而不是原始的遗留接口。

为了说明这个案例,我编写了一个抽象样本,以了解问题:

我有一个开发人员遗留父类:

public class Developer<C>{
    Rate<C> getRate(Taxes<C> tax){ /*...*/ }     
}

我还有一个Rentable传统界面,签名几乎相同

public interface Rentable {
    <C> Rate<C> getRate(Taxes<C> taxes);  
}

由于开发人员不可出租,在我的模型中,我创建了一个特殊的 开发人员既是开发人员又是可出租材料。

public class OutsourcableDeveloper<C> 
                 extends Developer<C> 
                 implements Rentable{
   @Override
   public Rate<C> getRate(Taxes<C> taxes){ /*...*/}
}

然后我得到了臭名昭着的

  

名称冲突:类型为getRate(Developer.Taxes)的方法   OutsourcableDeveloper具有相同的擦除功能   类似于Rentable的getRate(Developer.Taxes)但不会覆盖它

如何摆脱它,所以OutsourcableDeveloper.getRate()隐藏了 Developer和Rentable都是。的getRate()?

看起来有点不合逻辑地失败了一个普通的覆盖,但是随着删除是相同的,不允许延长两个签名。

事实上,其中一个超类型是从de方法中推断出来的,而另一个是从类中推断的,尤其是当我不打算在我的实现中调用任何超级时,这真的很重要吗?鉴于这种简化,是否有一个技巧可以克服这个问题?

编辑:我为我的实际问题打开了一个更抽象,更少解决方案,讨论继承设计问题的问题,我认为这是我遇到的实际问题的相关本质:Why can't I extend an interface "generic method" and narrow its type to my inherited interface "class generic"?

EDIT2:上一个问题引导我到这里发布的答案

2 个答案:

答案 0 :(得分:2)

他们实际上并不平等。因为任何Rentable-Instance允许给出任何类型参数T,而OutsourcableDeveloper限制它。

当然,您可以假设在您的情况下很容易使用

<C> Rate<C> getRate(Taxes<C> taxes);  

界面版本。但是如果他想要继承OutsourceableDeveloper,那么期望开发人员有多困惑。根据Developer的定义,他可以假设Method getRate固定为C,但实际上它可以突然取任何值。 - &GT;允许这会导致混淆。

我可以提供的是以下代码示例,它可能适合您的情况。虽然使用它肯定会不方便。但是当您将所有方法转发到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();
        }

    }
}

答案 1 :(得分:0)

好的,我找到了解决问题的方法。它是一团糟的,但如果架构不是很复杂,那么它就更容易了,受到Why can't I extend an interface "generic method" and narrow its type to my inherited interface "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”而不使用泛型类型,因此它显然是原始的。但我们也为非冲突方法打字输入