我用 Java 开发了很多代码,并涉足了 Groovy 和 Haskell,这让我现在转向了 Scala。
我对 Scala 的功能方面感觉比较舒服,但我发现自己在 Scala 中的面向对象设计上有点摇摆不定,因为它感觉与 Java 有点不同,特别是由于特征/混合。
我的目标是编写尽可能可测试的代码,这在我的 Java 开发中一直转化为专注于
- 尽可能的不变性
- 更喜欢由构造函数注入状态
- 总是选择组合而不是继承(受此帖子的严重影响,并且可能对 SO 上的帖子反应过度)
现在我正试图在这个新的 Scala 领域站稳脚跟,我很难弄清楚我应该在这里采用什么方法,特别是我是否应该开始出于某些目的使用继承。
Scala 编程(Wampler 和 Payne;O'Reilly,第 2 版)有一个考虑因素的部分(“良好的面向对象设计:题外话”),我已经阅读了一些关于 SO 的帖子,但我还没有看到明确提及可测试性的设计考虑。这本书提供了关于使用继承的建议:
- 抽象基类或特征由具体类(包括案例类)子类化一层。
- 具体类永远不会被子类化,除了两种情况:
- 混合在特征中定义的其他行为的类 (...)
- 仅测试版本以促进自动化单元测试。
- 当子类化似乎是正确的方法时,请考虑将行为划分为特征并混合这些特征。
- 永远不要跨父子类型边界拆分逻辑状态。
对 SO 的一些挖掘还表明,有时 mix-ins 比 composition 更可取。
所以本质上我有两个问题:
是否存在使用继承更好的常见情况,即使考虑到可测试性?
混入是否提供了增强代码可测试性的好方法?