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

时间:2016-02-07 04:58:40

标签: scala abstract-class abstract traits

我已经阅读过Scala,通常建议使用Traits而不是Abstract类来扩展基类。

以下是一个好的设计模式和布局吗?这是Traits如何取代Abstract?

  • 客户端类(使用def function1)
  • trait1 class(覆盖function1)
  • trait2 class(覆盖function1)
  • specificClient1使用trait1扩展客户端
  • specificClient2使用trait2扩展客户端

2 个答案:

答案 0 :(得分:67)

我不知道你的来源是什么声称你应该更喜欢scala中抽象类的特征,但有几个原因

  1. Traits使Java兼容性变得复杂。如果您具有伴随对象的特征,则从Java调用伴随对象上的方法需要奇怪的MyType$.MODULE$.myMethod语法。对于具有伴随对象的抽象类,情况并非如此,这些对象在JVM上作为具有静态和实例方法的单个类实现。使用Java中的具体方法实现Scala特性会更加令人不快。
  2. 以一种向类添加具体方法的方式,将具有实现的方法添加到特征breaks binary compatibility
  3. Traits会导致更多的字节码和一些与使用转发器方法相关的额外开销。
  4. 特征更强大,这是不好的 - 通常你想要使用功能最弱的抽象来完成工作。如果你不需要他们支持的那种多重继承(而且通常你不会),最好不要访问它。
  5. 在我看来,最后一个原因是迄今为止最重要的原因。在Scala的未来版本中至少还有一些其他问题might get fixed,但是默认情况下,默认情况下,这些问题将会以(至少可以说是与)良好设计一致的方式约束您的程序。如果你确定你真的真的想要特质提供的力量,他们仍然会在那里,但这将是你做出的决定,而不是你只是陷入其中。

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

答案 1 :(得分:2)

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

没有什么适合每种情况。使用正确的构造来完成手头的任务。有时,实现的现实会为设计时未知的特定用例带来问题。使用不同的假设和结构重新实现可以产生令人惊讶的结果。