混合 vs 特征

171
2个回答

235
  1. Mixins可以包含状态,(传统的)traits不行。
  2. Mixins使用“隐式冲突解决”,而traits使用“显式冲突解决”。
  3. Mixins依赖于线性化,traits被扁平化。

有关traits的讲座

ad 1. 在mixins中,您可以定义实例变量。Traits不允许这样做。状态必须由组合类(即使用traits的类)提供。

ad 2. 可能存在名称冲突。两个mixins(MAMB)或traits(TATB)定义相同定义的方法foo():void

Mixin MA {
    foo():void {
        print 'hello'
    }
}

Mixin MB {
    foo():void {
        print 'bye'
    }
}

Trait TA {
    foo():void {
        print 'hello'
    }
}

Trait TB {
    foo():void {
        print 'bye'
    }
}

在 mixin 中,组合类 C mixins MA, MB 的冲突是隐式解决的。

Class C mixins MA, MB {
    bar():void {
        foo();
    }
}

这将从MA调用foo():void

另一方面,使用Trait时,组合类必须解决冲突。

Class C mixins TA, TB {
    bar():void {
        foo();
    }
}

这段代码会引发冲突(定义了两个 foo():void)。

ad 3. 一个方法的语义不取决于它是在 trait 中定义还是在使用 trait 的类中定义。

换句话说,无论类是否由 Traits 组成,或者 Traits 代码被“复制粘贴”到类中,都没有关系。


6
我知道这已经过去一年了,但为了未来的读者,在Ruby中,它会使用最后混入的模块中的方法形式,因此它将调用MB中的foo()。 - rik.vanmechelen
4
在Scala中,特质(trait)可以有字段(fields),这意味着它们不是“传统”的特质吗? - Sergio
4
是的,这些不是“传统”的特征,它们被称为“具有状态的”特征。具有状态的特征和混合类之间的区别在于第二点和第三点。 - jk_
10
初步观察:术语"trait" 和 "mixin" 在实际应用中的使用方式极不一致,至少其中一个观点是大错特错的。PHP 和维基百科(还有据@Sergio称,Scala)与您对于 trait 是无状态的看法不同。我认为这个答案没有用处,因为它只是一些简单的断言,而且我不清楚这是否超出了您个人对这些词的使用。为了让我改变看法,我需要看到许多实例来支持您的说法,例如在真实编程语言中如何使用这些术语。 - Mark Amery
4
能否请您详细说明一下“Mixins depends on linearization, traits are flattened”这部分的意思?我不确定自己是否理解得正确。 - Adam Arold
显示剩余6条评论

9
这些页面解释了D编程语言的区别。

http://dlang.org/mixin.html

http://dlang.org/traits.html

在这个上下文中,混合(Mixins)是在编译时动态生成的代码,然后插入到代码中的那一点。对于简单的DSL非常方便。
特征(Traits)是编译时外部值(而不是从外部源生成的代码)。区别是微妙的。混合添加逻辑,特征添加数据,如编译时类型信息。
不太了解Ruby,但希望这有所帮助。

49
在D语言中,“Mixins”和“Traits”的含义与计算机科学领域中通常的含义完全不同。在D语言中,它们都是预处理器原语,用于自动生成代码。而在其他语言中,它们是继承机制。D语言中的命名决策是不幸的。 - tylerl

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接