【发布时间】:2020-11-13 15:24:50
【问题描述】:
假设我有一个接口Interface,它有一个方法aMethod(),它应该返回自己,但也有一个默认实现。然后我还有一个类Foo,它实现了Interface,并添加了额外的方法aFooMethod()。
interface Interface {
public default Interface aMethod() {
// Some code
return this;
}
}
class Foo implements Interface {
public void aFooMethod() {
// Some code
}
}
现在我无法调用new Foo().aMethod().aFooMethod();,因为aMethod() 返回一个Interface。
现在我显然可以继续并覆盖 Foo 中的方法:
class Foo implements Interface {
@Override
public Foo aMethod() {
Interface.super.aMethod();
return this;
}
public void aFooMethod() {
// Some code
}
}
我的问题是,如果有一个好的方法来强制这样做,子类必须返回自己而不必重写该方法?
我最好的方法是这样说:
interface Interface<I extends Interface<I>> {
@SupressWarnings("unchecked")
public default I aMethod() {
// Some code
return (I)this;
}
}
但这不是我认为的好,因为它必须使用SupressWarnings("unchecked")。有没有更好的办法?
【问题讨论】:
-
接口存在可能被多个子类子类化,有时在接口之后很长时间才创建。协变返回类型的便利性是这些子类的某些子集的实现细节。一种选择是让接口不了解子类的实现细节。
-
在我的例子中,我正在创建一个 Vector 接口。然后我有两个子类,Vector2D 和 Vector3D。因为即使你实际上没有固定数量的维度,如果你有它的大小,你也可以轻松地缩放一个向量,所以我想使用默认方法来完成所有这些。但是,这些链式方法调用不适用于特定于类的方法,例如请求 z 坐标,因为该方法只会返回 Vector,而不是 Vector3D,并且没有 z getter。我不得不重写所有默认方法只是为了返回一个 Vector3D,这并不是拥有默认方法的真正意义。
-
您是否考虑过实现接口的抽象类 AbstractVector,由 Vector2D 和 Vector3D 扩展,为具体子类提供一些受保护的缩放方法?例如,缩放一个大小取决于子类的数组?
-
4d 向量呢? 5天? 42天?如果数学家掌握了你的代码,你会遇到麻烦
-
@Andy Thomas 问题是 Vector2D 和 Vector3D 也有一些他们不共享的方法,例如叉积(返回 3D 的 Vector,2D 的双精度)或旋转(显然可以'不只用一个角度表达 3D 旋转)所以另一个抽象类不会真正有意义,因为实际的类仍然必须使用覆盖返回自身
标签: java generics inheritance