在Scala中混合多重特性

快速提示:来自Java难民Scala教程第5部分:特性和types的示例。

假设我有学生,工人,欠薪和年轻的特质。

我怎么能申报一个class( 不是实例 ),学院学生,所有这些特质?

注意:我知道最简单的例子,比如有一两个特质的大学学生:

class CollegeStudent extends Student with Worker 

很容易,在声明一个类的时候,你只需要经常使用“with”关键字

 class CollegeStudent extends Student with Worker with Underpaid with Young 

如果一个特质正在改变class级的行为,那么特质的顺序就可能是重要的,这一切都取决于你正在使用的特质。

另外如果你不想有一个总是使用相同特质的课程,你可以稍后使用它们:

 class CollegeStudent extends Student new CollegeStudent with Worker with Underpaid with NotSoYoungAnymore 

我认为,不仅要解释语法,而且还要解释特质sorting扮演的angular色 ,这一点非常重要。 我在Jason Swartz的学习Scala (177页)中find了相当有启发性的解释。

  • 一个Scala类可以一次扩展多个特征,但是JVM类只能扩展一个父类。 Scala编译器通过创build“ 每个特征的副本以形成类和特征的高单列层次结构 ”(一种称为线性化的过程)来解决这个问题。

  • 在这种情况下,扩展具有相同字段名称的多个特性将无法编译,就像“ 扩展一个类并提供您自己的方法版本但未添加覆盖关键字 ”一样。

而由于它决定了inheritance树的形状,所以线性化的顺序确实是一个非常重要的问题。 作为一个例子, class D extends A with B with C (其中A是一个类,B和C是特征)将成为class D extends C extends B extends A 下面这几行也从这本书中可以很好地说明:

 trait Base { override def toString = "Base" } class A extends Base { override def toString = "A->" + super.toString } trait B extends Base { override def toString = "B->" + super.toString } trait C extends Base { override def toString = "C->" + super.toString } class D extends A with B with C { override def toString = "D->" + super.toString } 

调用new D()将使REPL打印以下内容:

  D->C->B->A->Base 

这完美地反映了线性化遗传图的结构。