为分层实体设计接口 [英] Designing interface for hierarchical entity

查看:118
本文介绍了为分层实体设计接口的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我必须为分层实体设计一个接口:

  interface HierarchicalEntity< T extends HierarchicalEntity< T>> {
T getParent();
Stream< T> getAncestors();
}

实施默认 <$ c非常容易$ c> getAncestors()以 getParent()的方式,前者将返回 Stream 所有祖先。



实施例:

 默认流< T> getAncestors(){
Stream.Builder< T> parentsBuilder = Stream.builder();
T parent = getParent();
while(parent!= null){
parentsBuilder.add(parent);
parent = parent.getParent();
}
返回parentsBuilder.build();
}

但我还需要包含这个进入流,这里出现问题。
以下行不正确,因为的类型为 HierarchicalEntity ,而不是 T

  parentsBuilder.add(this); // 类型不匹配! 

如何重新设计界面以使 getAncestors()在结果中包含

解决方案

这是创建自引用类型时反复出现的问题。在基本类型(或接口)中,您不能强制执行将与 T 兼容。 / p>

当然,您可以执行未经检查的转换为 T 如果您确信所有子类型都能满足该约束条件。但是当你需要这个引用时,你必须执行这个未经检查的强制转换为 T



更好的解决方案是添加一个抽象方法,如

  / ** 
全部子类型应该实现为:

public T myself(){
return this;
}
* /
public abstract T myself();

然后,您可以使用我自己()而不是这个,只要你需要自我引用为 T

 默认流< T> getAncestors(){
Stream.Builder< T> parentsBuilder = Stream.builder();
for(T node = myself(); node!= null; node = node.getParent()){
parentsBuilder.add(parent);
}
返回parentsBuilder.build();
}

当然,您无法强制执行该子类正确实现我自己()作为返回此; ,但至少,您可以轻松验证它们是否在运行时执行:

 断言这个==我自己(); 

这个参考比较是一个非常便宜的操作,如果我自己()正确实现为总是返回,HotSpot可以提前证明此比较将始终为 true 并完全取消支票。



缺点是每个专业化必须有我自己()的冗余实现{return this; } ,但另一方面,它完全没有未经检查的类型转换。另一种方法是在基类中将 abstract 的非 abstract 声明为 @SuppressWarnings(unchecked)T我自己(){return(T)this; } 将未经检查的操作限制为类型层次结构的单个位置。但是,你无法验证这个是否真的属于 T ...


I have to design an interface for hierarchical entity:

interface HierarchicalEntity<T extends HierarchicalEntity<T>> {
    T getParent();
    Stream<T> getAncestors();
}

It's quite easy to implement default getAncestors() method in terms of getParent() in such a way that the former would return Stream of all the ancestors.

Implementation example:

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();
}

But I need to also include this into the stream, and here a problem appears. The following line is not correct because this is of type HierarchicalEntity, not T:

parentsBuilder.add(this); // type mismatch!

How can I redesign the interface in order to make getAncestors() include this into the result?

解决方案

It’s a recurring problem when creating self-referential types. In the base type (or interface), you can’t enforce that this will be assignment compatible with T.

Of course, you can perform an unchecked cast of this to T if you are confident that all subtypes will fulfill that constraint. But you have to perform this unchecked cast whenever you need a this reference as T.

The better solution is to add an abstract method like

/**
    All subtypes should implement this as:

    public T myself() {
        return this;
    }
 */
public abstract T myself();

Then, you can use myself() instead of this whenever you need a self-reference as T.

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();
}

Of course, you can’t enforce that subclasses correctly implement myself() as return this;, but at least, you can easily verify whether they do at runtime:

assert this == myself();

This reference comparison is a very cheap operation and, if myself() is correctly implemented as invariably returning this, HotSpot can prove in advance that this comparison will always be true and elide the check completely.

The drawback is that each specialization will have to have this redundant implementation of myself() { return this; }, but on the other hand, it’s completely free of unchecked type casts. The alternative is to have an non-abstract declaration of myself() in the base class as @SuppressWarnings("unchecked") T myself() { return (T)this; } to limit the unchecked operation to a single place for the type hierarchy. But then, you can’t verify whether this really is of type T

这篇关于为分层实体设计接口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆