我正在创建一个覆盖方法签名的类,该方法签名的擦除在两个实现的接口之间是相同的,但在泛型类型方面存在细微差别(一个是方法推断类型,另一个是推断类类型) 。我正在寻找一个简洁的解决方案。我只能编辑继承的类,而不是原始的遗留接口。
为了说明这个案例,我编写了一个抽象样本,以了解问题:
我有一个开发人员遗留父类:
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:上一个问题引导我到这里发布的答案
答案 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”而不使用泛型类型,因此它显然是原始的。但我们也为非冲突方法打字输入