我必须为分层实体设计一个接口(interface):
interface HierarchicalEntity<T extends HierarchicalEntity<T>> {
T getParent();
Stream<T> getAncestors();
}
默认很容易实现getAncestors()
getParent()
方面的方法以这样的方式前者会返回Stream
所有的祖先。
实现示例:
default Stream<T> getAncestors() {
Stream.Builder<T> parentsBuilder = Stream.builder();
T parent = getParent();
while (parent != null) {
parentsBuilder.add(parent);
parent = parent.getParent();
}
return parentsBuilder.build();
}
但我还需要包括 this
进入流,这里出现了一个问题。
以下行不正确,因为 this
类型为 HierarchicalEntity
, 不是 T
:
parentsBuilder.add(this); // type mismatch!
我怎样才能重新设计界面以制作getAncestors()
包括 this
进入结果?
最佳答案
这是创建自引用类型时反复出现的问题。在基类型(或接口(interface))中,您不能强制要求 this
的赋值与 T
兼容。
当然,如果您确信所有子类型都将满足该约束,则可以执行未检查的 this
到 T
的转换。但是,只要您需要将 this
引用为 T
,就必须执行此未经检查的转换。
更好的解决方案是添加一个抽象方法,如
/**
All subtypes should implement this as:
public T myself() {
return this;
}
*/
public abstract T myself();
然后,只要您需要将自引用作为 T
,就可以使用 myself()
而不是 this
。
default Stream<T> getAncestors() {
Stream.Builder<T> parentsBuilder = Stream.builder();
for(T node = myself(); node != null; node = node.getParent()) {
parentsBuilder.add(parent);
}
return parentsBuilder.build();
}
当然,您不能强制子类正确实现 myself()
作为 return this;
,但至少,您可以轻松验证它们是否在运行时执行:
assert this == myself();
这个引用比较是一个非常便宜的操作,如果 myself()
被正确地实现为总是返回 this
,HotSpot 可以提前证明这个比较总是true
并完全省略检查。
缺点是每个特化都必须有 myself() { return this; 的冗余实现。 }
,但另一方面,它完全没有未经检查的类型转换。另一种方法是在基类中对 myself()
进行非抽象
声明,如 @SuppressWarnings("unchecked") T myself() { return ( T)这个; }
将未经检查的操作限制在类型层次结构的单个位置。但是,你无法验证 this
是否真的是 T
类型......
关于java - 为分层实体设计界面,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37078814/