当前位置: 首页 > 面试题库 >

分层实体的设计界面

田博易
2023-03-14
问题内容

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

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在结果中?


问题答案:

创建自引用类型时,这是一个反复出现的问题。在基本类型(或接口)中,您不能强制this将与分配兼容T

当然,如果您确信所有子类型都将满足该约束thisT则可以执行to
的未经检查的强制转换。但是,无论何时需要this引用为,都必须执行此未经检查的强制转换T

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

/**
    All subtypes should implement this as:

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

然后,您可以使用,myself()而不是this在需要自引用时使用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();
}

当然,您不能强制将子类正确实现myself()return this;,但是至少,您可以轻松地验证它们是否在运行时执行:

assert this == myself();

该参考比较是一项非常便宜的操作,如果myself()正确地实现为不变地返回this,HotSpot可以提前证明该比较将始终存在true并完全消除检查。

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



 类似资料:
  • 分层的库设计 每个Subversion核心模块都属于三层中的某一层—版本库层、版本库访问(RA)层或是客户端层(见图 1 “Subversion的架构”)。我们很快就会考察这些层,但首先让我们看一下Subversion库的摘要目录,为了一致性,我们将通过它们的无扩展Unix库名(例如libsvn_fs、libsvn_wc和mod_dav_svn)来引用它们。 libsvn_client 客户端程序

  • 我有3个实体- > 课程 组件 时间线课程是一个独立的实体,具有以下属性:课程-(id Integer主键,Course_name) @ Id @ Column(name = " Id ")Integer courseId;@Column(name = "course_name ")字符串course _ name; 接下来是另一个实体模块,模块中的每一行都与一门课程相关,因此模块和课程之间存在一

  • 扩展的交互界面应该是有目的且最简单的。 就像扩展本身一样,界面 UI 应该是自定义或能增强浏览体验,而不会分散用户注意力。 本指南探讨了必需的和可选的用户界面功能,了解如何以及何时在扩展中实现不同的 UI 元素。 在所有页面上激活扩展 当扩展程序的功能在大多数情况下都可以使用时,请使用 browser_action 。 注册 browser_action browser_action 在 mani

  • 4.3.1 顶层设计 根据 calendar 程序的规格说明,很容易设计一个简单的 IPO 模式的算法:首先从用户处 获得年份输入 year,然后计算该年份 1 月 1 日是星期几,最后按特定格式输出年历。我们用 伪代码来表示该算法,如下: 输入 year 计算 year 年 1 月 1 日是星期几 输出年历 这个算法属于高层设计,其中第二、第三两个步骤都不是一目了然能直接编码实现的, 但我们不

  • 注:本节未经校验,如有问题欢迎提issue akka.io 包已由Akka和spray.io 团队协作开发。其设计采用spray-io 模块的开发经验,并加以改进为更一般基于actor的服务使用。 要求 为了形成通用的可扩展的IO层基础,使之适合于广泛的应用,在Akka remoting 和spray HTTP 是原有基础上,为设计的关键驱动因素建立了以下要求: 数以百万计的并发连接的可扩展性 从

  • 主要内容:本节引言:,Mockplus原型工具的使用:,Android自带DroidDraw工具设计Android界面:,本节小结:本节引言: 引用锤子科技视觉设计总监——罗子雄在重庆TEDx活动上说的一小段话: 每当我们看到一些美妙的设计的时候,很多人心里面会有一种冲动,这种冲动会让你们想去创造一些 新的东西,创造一些美妙的事物。 我们常说用户体验用户体验,用户使用你的软件,第一个会接触的是什么?没错,图形化界面(GUI),简称UI,对于用户而言,最直观,给用户留下第一印像的是往往是程序的界面