具有 Traits 的 Scala 客户端组合与实现抽象 class

Scala client composition with Traits vs implementing an abstract class

我读过关于 Scala 的内容,通常建议使用 Traits 而不是 Abstract classes 来扩展基础 class。

以下是好的设计模式和布局吗?这就是 Traits 取代 Abstract 的方式吗?

我不知道你声称在 Scala 中你应该更喜欢 traits 而不是抽象 classes 的来源是什么,但是有几个原因 not :

  1. 特性使 Java 兼容性复杂化。如果你有伴生对象的特征,从 Java 调用伴生对象的方法需要奇怪的 MyType$.MODULE$.myMethod 语法。对于带有伴随对象的抽象 classes 不是这种情况,它们在 JVM 上作为单个 class 实现,具有静态和实例方法。在 Java 中使用具体方法实现 Scala 特征更令人不快。
  2. 将具有实现的方法添加到特征 breaks binary compatibility 的方式与将具体方法添加到 class 不同。
  3. 特征导致更多的字节码和一些与使用转发器方法相关的额外开销。
  4. 特征更强大,这是不好的——通常你想使用最不强大的抽象来完成工作。如果您不需要他们支持的那种多重继承(通常您不需要),最好不要访问它。

在我看来,最后一个原因是迄今为止最重要的。在 Scala 的未来版本中至少还有其他一些问题 might get fixed,但默认为 classes 的情况仍然会以(至少可以说)符合良好标准的方式限制您的程序设计。如果你决定你真的真的想要特性提供的力量,它们仍然会存在,但这将是你做出的决定,而不是你随便进入的东西。

所以不,在没有其他信息的情况下,我建议使用抽象 class(最好是密封的)和两个提供实现的具体 classes。

OTOH,特征允许您以细粒度的方式构建和测试复杂对象的功能,并重用核心逻辑以提供不同的风格。例如,域对象可能部署到数据服务器,该数据服务器持久保存到数据库,而 Web 服务器可能使用从数据服务器更新的同一对象的只读版本。

没有什么是适合所有场景的。为手头的任务使用正确的结构。有时,实施的现实会揭示设计时未知的特定用例的问题。使用不同的假设和构造重新实施可能会产生令人惊讶的结果。