gpt4 book ai didi

java - 绑定(bind)两个泛型

转载 作者:塔克拉玛干 更新时间:2023-11-02 19:34:30 25 4
gpt4 key购买 nike

我有一个关于泛型的问题。我有以下接口(interface):

public interface InterfaceA<B extends InterfaceA.InterfaceB> {

public interface InterfaceB<A extends InterfaceA> {

void setA(A a);
}
}

InterfaceA 的抽象实现如下:

public abstract class AImplOne<B extends InterfaceA.InterfaceB> implements InterfaceA<B> {

private final B b;

public AImplOne(B b) {
this.b = b;
b.setA(this); // <-- Unchecked call...
}
}

我很清楚调用 b.setA(this) 是未选中的 - 但我不喜欢它,所以我尝试了第二个抽象实现:

public abstract class AImplTwo<A extends InterfaceA, B extends InterfaceA.InterfaceB<A>> implements InterfaceA<B> {

private final B b;

public AImplTwo(B b) {
this.b = b;
b.setA((A)this); // <-- Unchecked cast
}
}

再一次,我很清楚调用 b.setA((A)this) 是一个未检查的转换。

但是应该如何实现或重新设计才能摆脱未经检查的代码?

最佳答案

你实际上有一个相互递归的泛型定义,你通过使用原始类型来打破它:在

b.setA((A)this); // <- Unchecked cast

this类型为 InterfaceA<? extends InterfaceA.InterfaceB<? extends InterfaceA>> , 但它应该是 InterfaceA<? extends InterfaceA.InterfaceB<? extends InterfaceA<? extends InterfaceA.InterfaceB<...>>>> 类型.你将不得不使用

public interface InterfaceA<B extends InterfaceA.InterfaceB<?>> {

public interface InterfaceB<A extends InterfaceA<B>> { //<- cannot make a static reference to the non-static type B

void setA(A a);
}
}

但是你不能使用B ,它是非静态的,在静态接口(interface)声明中(接口(interface)声明始终是静态的)。


有关详细信息,请进一步尝试:使用替代方法

public interface InterfaceA<B extends InterfaceA.InterfaceB<?>> {

public interface InterfaceB<A extends InterfaceA<? extends InterfaceA.InterfaceB<?>>> {

void setA(A a);
}
}


abstract class AImplTwo<B extends InterfaceA.InterfaceB<A>, A extends InterfaceA<B>> implements InterfaceA<B> {

private final B b;

public AImplTwo(B b) {
this.b = b;
b.setA((A)this); // <-- Unchecked cast
}
}

再次导致未经检查的转换,因为现在 InterfaceA 的嵌套类型参数在 interface InterfaceB<A extends InterfaceA<? extends InterfaceA.InterfaceB<?>>>又是 InterfaceA.InterfaceB<?> 的任意子类.


更新,因为您要求的是通用设计:

我会将 InterfaceB(实际上,一般意义上的接口(interface))视为具体实现的抽象:在 InterfaceA 的实现中,您只需要接口(interface) InterfaceB,而不需要其实现细节。将 InterfaceB 视为契约(Contract),您不关心实现。因此不需要将 InterfaceA 的实现绑定(bind)到 InterfaceB 的实现:

public interface InterfaceA {

public interface InterfaceB {

void setA(InterfaceA a);
}
}

只有当出于我看不到的原因,您确实希望您正在使用的所有 InterfaceB 实例都具有相同的类型时,您才需要泛型。 InterfaceA 反之亦然。使用上面最后一个泛型示例,您至少可以修复 InterfaceA 和 InterfaceB 的类型,并且只需要动态断言 A 的 B 和 B 的 A 是相同的。

显示在 Java 中不存在类型检查的解决方案是困难的,但是通过下面的示例可能会变得合理,如果 Java 允许 extends 和 super 的组合,这将是一个解决方案:

public interface A<TB extends A.B<?>> {

public interface B<TA extends A<? extends A.B<?>>> {

void setA(TA a);
}
}


class AImplTwo<TB extends A.B<TA>, TA extends AImplTwo<TB, TA> super AImplTwo<TB, TA>> implements A<TB> {

private final TB b;

public AImplTwo(TB b) {
this.b = b;
b.setA((TA)this);
}
}

...想想看,可插入类型系统为 Java 添加了更多的类型,它允许扩展和 super 的这种组合,因此可能会为您的问题提供解决方案。但我发现它对于你得到的东西来说太复杂了,并且要么坚持简单地使用没有泛型的接口(interface),要么坚持使用一些未经检查的转换。

关于java - 绑定(bind)两个泛型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9598538/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com