Ali*_*der 7 java interface hierarchical java-8 default-method
我必须为分层实体设计一个接口:
interface HierarchicalEntity<T extends HierarchicalEntity<T>> {
T getParent();
Stream<T> getAncestors();
}
Run Code Online (Sandbox Code Playgroud)
以前者将返回所有祖先的方式实现默认 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();
}
Run Code Online (Sandbox Code Playgroud)
但是我还需要包含this在流中,这里出现问题.以下行不正确,因为this它是类型HierarchicalEntity,而不是T:
parentsBuilder.add(this); // type mismatch!
Run Code Online (Sandbox Code Playgroud)
如何重新设计界面以使getAncestors()包含this到结果中?
创建自引用类型时,它\xe2\x80\x99 是一个反复出现的问题。在基本类型(或接口)中,您可以\xe2\x80\x99t 强制执行this与T.
当然,如果您确信所有子类型都满足该约束,则可以执行thisto的未经检查的强制转换。T但是,只要您需要引用thisas ,就必须执行这种未经检查的转换T。
更好的解决方案是添加一个抽象方法,例如
\n\n/**\n All subtypes should implement this as:\n\n public T myself() {\n return this;\n }\n */\npublic abstract T myself();\nRun Code Online (Sandbox Code Playgroud)\n\n然后,当您需要自引用时,您可以使用myself()而不是as 。thisT
default Stream<T> getAncestors() {\n Stream.Builder<T> parentsBuilder = Stream.builder();\n for(T node = myself(); node != null; node = node.getParent()) {\n parentsBuilder.add(parent);\n }\n return parentsBuilder.build();\n}\nRun Code Online (Sandbox Code Playgroud)\n\n当然,您可以\xe2\x80\x99t强制子类正确实现myself()为return this;,但至少,您可以轻松验证它们是否在运行时执行:
assert this == myself();\nRun Code Online (Sandbox Code Playgroud)\n\n这种引用比较是一种非常便宜的操作,如果myself()正确实现为总是返回this,HotSpot 可以提前证明这种比较将始终是true并且完全消除检查。
缺点是每个专门化都必须有 的冗余实现myself() { return this; },但另一方面,它\xe2\x80\x99s 完全没有未经检查的类型转换。另一种方法是在基类中进行非abstract声明,以将未经检查的操作限制在类型层次结构的单个位置。但是,你可以\xe2\x80\x99t验证是否真的是\xe2\x80\xa6类型myself()@SuppressWarnings("unchecked") T myself() { return (T)this; }thisT
| 归档时间: |
|
| 查看次数: |
166 次 |
| 最近记录: |