名称冲突,覆盖失败,在 class 上实现两个具有相同擦除的接口
Name Clash, override fail, on a class implementing two interfaces with same erasure
我正在创建一个 class 来覆盖方法签名,其擦除在 2 个已实现的接口之间是相同的,但在泛型类型方面有细微差别(一个是 method-inferred 类型,另一个 inferred-class 类型)。我正在寻找一个简洁的解决方案。我只能编辑继承的 class,不能编辑原始的遗留界面。
为了展示案例,我做了一个抽象示例,以理解问题:
我得到了开发者的遗产 parent class:
public class Developer<C>{
Rate<C> getRate(Taxes<C> tax){ /*...*/ }
}
我还有一个 Rentable 遗留界面,签名几乎相同
public interface Rentable {
<C> Rate<C> getRate(Taxes<C> taxes);
}
由于开发人员不可出租,在我的模型中,我创建了一个特殊的
developer 既是开发商,又是可出租的 material.
public class OutsourcableDeveloper<C>
extends Developer<C>
implements Rentable{
@Override
public Rate<C> getRate(Taxes<C> taxes){ /*...*/}
}
然后我得到了臭名昭著的
Name clash: The method getRate(Developer.Taxes) of type
OutsourcableDeveloper has the same erasure as
getRate(Developer.Taxes) of type Rentable but does not override it
怎么去掉,所以OutsourcableDeveloper.getRate()隐藏了
开发商和可出租的。 getRate()?
似乎有点不合逻辑,让一个共同的覆盖失败,然后又不允许扩展两个签名,因为擦除是相等的。
其中一个超类型从 de 方法推断类型而另一个从 class 推断类型这一事实真的很重要吗,特别是当我不打算在我的实现中调用任何超类时?考虑到这种简化,是否有解决此问题的技巧?
编辑:我对我的实际问题打开了一个更抽象、更少 solution-oriented 的问题来讨论继承设计问题,我认为这是我遇到的实际问题的相关本质:
EDIT2:上一个问题引导我找到此处发布的答案
其实他们并不相等。因为任何Rentable-Instance都允许给定任何类型参数T,而OutsourcableDeveloper限制了。
当然你可以假设在你的情况下很容易使用
<C> Rate<C> getRate(Taxes<C> taxes);
接口版本。但是,如果开发人员想要继承 OutsourceableDeveloper
,他会感到多么困惑。根据 Developer 的定义,他可以假设方法 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();
}
}
}
好的,我找到了解决方法。它很笨拙,但如果架构不是很复杂,它会更容易,灵感来自我 自己的答案:
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",所以它是隐式原始的。但我们也放宽了非冲突方法的类型
我正在创建一个 class 来覆盖方法签名,其擦除在 2 个已实现的接口之间是相同的,但在泛型类型方面有细微差别(一个是 method-inferred 类型,另一个 inferred-class 类型)。我正在寻找一个简洁的解决方案。我只能编辑继承的 class,不能编辑原始的遗留界面。
为了展示案例,我做了一个抽象示例,以理解问题:
我得到了开发者的遗产 parent class:
public class Developer<C>{
Rate<C> getRate(Taxes<C> tax){ /*...*/ }
}
我还有一个 Rentable 遗留界面,签名几乎相同
public interface Rentable {
<C> Rate<C> getRate(Taxes<C> taxes);
}
由于开发人员不可出租,在我的模型中,我创建了一个特殊的 developer 既是开发商,又是可出租的 material.
public class OutsourcableDeveloper<C>
extends Developer<C>
implements Rentable{
@Override
public Rate<C> getRate(Taxes<C> taxes){ /*...*/}
}
然后我得到了臭名昭著的
Name clash: The method getRate(Developer.Taxes) of type OutsourcableDeveloper has the same erasure as getRate(Developer.Taxes) of type Rentable but does not override it
怎么去掉,所以OutsourcableDeveloper.getRate()隐藏了 开发商和可出租的。 getRate()?
似乎有点不合逻辑,让一个共同的覆盖失败,然后又不允许扩展两个签名,因为擦除是相等的。
其中一个超类型从 de 方法推断类型而另一个从 class 推断类型这一事实真的很重要吗,特别是当我不打算在我的实现中调用任何超类时?考虑到这种简化,是否有解决此问题的技巧?
编辑:我对我的实际问题打开了一个更抽象、更少 solution-oriented 的问题来讨论继承设计问题,我认为这是我遇到的实际问题的相关本质:
EDIT2:上一个问题引导我找到此处发布的答案
其实他们并不相等。因为任何Rentable-Instance都允许给定任何类型参数T,而OutsourcableDeveloper限制了。
当然你可以假设在你的情况下很容易使用
<C> Rate<C> getRate(Taxes<C> taxes);
接口版本。但是,如果开发人员想要继承 OutsourceableDeveloper
,他会感到多么困惑。根据 Developer 的定义,他可以假设方法 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();
}
}
}
好的,我找到了解决方法。它很笨拙,但如果架构不是很复杂,它会更容易,灵感来自我
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",所以它是隐式原始的。但我们也放宽了非冲突方法的类型