具有 Traits 的 Scala 客户端组合与实现抽象 class
Scala client composition with Traits vs implementing an abstract class
我读过关于 Scala 的内容,通常建议使用 Traits 而不是 Abstract classes 来扩展基础 class。
以下是好的设计模式和布局吗?这就是 Traits 取代 Abstract 的方式吗?
- 客户端class(使用 def 函数 1)
- 特质 1 class(覆盖功能 1)
- 特征 2 class(覆盖功能 1)
- specificClient1 使用 trait1 扩展客户端
- specificClient2 使用 trait2 扩展客户端
我不知道你声称在 Scala 中你应该更喜欢 traits 而不是抽象 classes 的来源是什么,但是有几个原因 not :
- 特性使 Java 兼容性复杂化。如果你有伴生对象的特征,从 Java 调用伴生对象的方法需要奇怪的
MyType$.MODULE$.myMethod
语法。对于带有伴随对象的抽象 classes 不是这种情况,它们在 JVM 上作为单个 class 实现,具有静态和实例方法。在 Java 中使用具体方法实现 Scala 特征更令人不快。
- 将具有实现的方法添加到特征 breaks binary compatibility 的方式与将具体方法添加到 class 不同。
- 特征导致更多的字节码和一些与使用转发器方法相关的额外开销。
- 特征更强大,这是不好的——通常你想使用最不强大的抽象来完成工作。如果您不需要他们支持的那种多重继承(通常您不需要),最好不要访问它。
在我看来,最后一个原因是迄今为止最重要的。在 Scala 的未来版本中至少还有其他一些问题 might get fixed,但默认为 classes 的情况仍然会以(至少可以说)符合良好标准的方式限制您的程序设计。如果你决定你真的真的想要特性提供的力量,它们仍然会存在,但这将是你做出的决定,而不是你随便进入的东西。
所以不,在没有其他信息的情况下,我建议使用抽象 class(最好是密封的)和两个提供实现的具体 classes。
OTOH,特征允许您以细粒度的方式构建和测试复杂对象的功能,并重用核心逻辑以提供不同的风格。例如,域对象可能部署到数据服务器,该数据服务器持久保存到数据库,而 Web 服务器可能使用从数据服务器更新的同一对象的只读版本。
没有什么是适合所有场景的。为手头的任务使用正确的结构。有时,实施的现实会揭示设计时未知的特定用例的问题。使用不同的假设和构造重新实施可能会产生令人惊讶的结果。
我读过关于 Scala 的内容,通常建议使用 Traits 而不是 Abstract classes 来扩展基础 class。
以下是好的设计模式和布局吗?这就是 Traits 取代 Abstract 的方式吗?
- 客户端class(使用 def 函数 1)
- 特质 1 class(覆盖功能 1)
- 特征 2 class(覆盖功能 1)
- specificClient1 使用 trait1 扩展客户端
- specificClient2 使用 trait2 扩展客户端
我不知道你声称在 Scala 中你应该更喜欢 traits 而不是抽象 classes 的来源是什么,但是有几个原因 not :
- 特性使 Java 兼容性复杂化。如果你有伴生对象的特征,从 Java 调用伴生对象的方法需要奇怪的
MyType$.MODULE$.myMethod
语法。对于带有伴随对象的抽象 classes 不是这种情况,它们在 JVM 上作为单个 class 实现,具有静态和实例方法。在 Java 中使用具体方法实现 Scala 特征更令人不快。 - 将具有实现的方法添加到特征 breaks binary compatibility 的方式与将具体方法添加到 class 不同。
- 特征导致更多的字节码和一些与使用转发器方法相关的额外开销。
- 特征更强大,这是不好的——通常你想使用最不强大的抽象来完成工作。如果您不需要他们支持的那种多重继承(通常您不需要),最好不要访问它。
在我看来,最后一个原因是迄今为止最重要的。在 Scala 的未来版本中至少还有其他一些问题 might get fixed,但默认为 classes 的情况仍然会以(至少可以说)符合良好标准的方式限制您的程序设计。如果你决定你真的真的想要特性提供的力量,它们仍然会存在,但这将是你做出的决定,而不是你随便进入的东西。
所以不,在没有其他信息的情况下,我建议使用抽象 class(最好是密封的)和两个提供实现的具体 classes。
OTOH,特征允许您以细粒度的方式构建和测试复杂对象的功能,并重用核心逻辑以提供不同的风格。例如,域对象可能部署到数据服务器,该数据服务器持久保存到数据库,而 Web 服务器可能使用从数据服务器更新的同一对象的只读版本。
没有什么是适合所有场景的。为手头的任务使用正确的结构。有时,实施的现实会揭示设计时未知的特定用例的问题。使用不同的假设和构造重新实施可能会产生令人惊讶的结果。