Mixins vs scala中的组合

在Java世界中(更准确地说,如果你没有多重继承/混合),经验法则很简单:“赞成对象组合超越类继承”。

我想知道如果你还考虑mixins,特别是在scala中它是如何改变的?
mixin被认为是多重继承的一种方式,还是更多的类构成?
是否还有“赞成课堂作文以上类别作文”(或其他方式)指导方针?

当人们使用(或滥用)mixins时,我看到了一些例子,当对象组合也可以完成这项工作时,我并不总能确定哪一个更好。 在我看来,你可以与他们完成类似的事情,但也有一些差异,例如:

  • 知名度 - 与mixin一切都成为公共API的一部分,组合并非如此。
  • 详细程度 - 在大多数情况下,mixin不那么冗长且易于使用,但情况并非总是如此(例如,如果您还在复杂层次结构中使用自我类型)
  • 我知道简短的答案是“这取决于”,但当这个或那个更好时,可能会有一些典型的情况。

    目前我可以提出的一些指导方针示例(假设我有两个特征A和B,而A想使用B的某些方法):

  • 如果你想用B的方法扩展A的API,那么混合,否则组合。 但是,如果我创建的类/实例不是公共API的一部分,它就没有帮助。
  • 如果你想使用一些需要mixin的模式(例如Stackable Trait Pattern),那么这是一个简单的决定。
  • 如果你有循环依赖,那么mixins和self类型可以提供帮助。 (我尽量避免这种情况,但并非总是那么容易)
  • 如果你想要一些动态的,运行时决定如何做组合然后对象组成。
  • 在很多情况下,mixins看起来更容易(和/或不太详细),但我确定他们也有一些陷阱,比如两个artima文章中描述的“上帝阶级”和其他一些陷阱:第1部分,第2部分在我看来,大多数其他问题与scala不相关/不那么严重)。

    你有更多这样的提示吗?


    如果您只将抽象特征混入您的类定义中,并且在对象实例化时混合相应的具体特征,那么人们在Scala中可以避免很多混淆问题。 例如

    trait Locking{
       // abstract locking trait, many possible definitions
       protected def lock(body: =>A):A
    }
    
    class MyService{
       this:Locking =>
    }
    
    //For this time, we'll use a java.util.concurrent lock
    val myService:MyService = new MyService with JDK15Locking 
    

    这个构造有几件事情可以推荐它。 首先,由于需要特征功能的不同组合,因此防止了类的爆炸。 其次,它允许简单的测试,因为人们可以创建和混入“无所事事”的具体特征,类似于模拟对象。 最后,我们已经完全隐藏了使用的锁定特征,甚至锁定正在发生,从我们的服务的消费者。

    由于我们已经过去了混音的大部分缺陷,我们仍然在混音和合成之间进行权衡。 对于我自己,我通常会根据假设的委托对象是否完全被包含对象封装,或者它是否可能被共享并拥有它自己的生命周期来作出决定。 锁定提供了一个完全封装代理的好例子。 如果您的类使用锁对象来管理对其内部状态的并发访问,则该锁完全由包含对象控制,并且它的操作和操作都不作为类public interface的一部分进行公布。 对于像这样完全封装的功能,我会使用混合插件。 对于共享的东西,如数据源,使用组合。


    你还没有提到的其他差异:

  • 特质类没有任何独立存在:
  • (编程斯卡拉)

    如果你发现一个特定的特征经常被用作其他类的父类,那么这些子类就像父特征一样,然后考虑将特征定义为类,以使这种逻辑关系更加清晰。
    (我们说的行为是,而不是一个,因为前者是继承的更精确的定义,基于Liskov替代原则 - 例如参见[Martin2003])。

    [Martin2003]:Robert C. Martin,Agile Software Development:Principles,Patterns,and Practices,Prentice-Hall,2003

  • mixins( trait )没有构造函数参数。
  • 因此,这些建议仍然来自Programming Scala:

    避免无法将初始化为适当默认值的特征中的混凝土字段。
    改为使用抽象字段, 或使用构造函数将特征转换为类
    当然,无状态特征在初始化时没有任何问题。

    这是一个良好的面向对象设计的一般原则, 即一个实例应始终处于已知的有效状态,从构建过程完成的那一刻开始

    关于对象的初始状态 ,最后一部分经常帮助确定一个给定概念的类(和类的构成)和特征(和混合类)之间的关系。

    链接地址: http://www.djcxy.com/p/54829.html

    上一篇: Mixins vs composition in scala

    下一篇: Multiple Inheritance from two derived classes