2009-07-05 19 views
42

快速提示:示例来自教程Scala for Java Refugees Part 5: Traits and Types在Scala中混合多重特性

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

我该如何申报一个班级(而不是实例),CollegeStudent,具备所有这些特质?

注:我知道的simplests情况下,如CollegeStudent有一个或两个特点:

class CollegeStudent extends Student with Worker 
+1

???问一个问题,然后自我调整 – 2009-07-05 18:36:56

+0

很久以前,我曾在Eclipse上尝试过一次,但这并没有奏效。升级之后,写下测试我想:“也许我会尝试一下,看看我能否自己找到它”。 – 2009-07-05 20:59:53

回答

86

这是很容易,声明一个类时,你只是“同向”经常关键字使用只要你想

class CollegeStudent extends Student with Worker with Underpaid with Young 

如果性状改变类的行为特征的顺序也很重要,这一切都取决于你所使用的特征。

此外,如果你不希望有它总是使用相同性状的类,你可以在以后使用它们:

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

我认为,这说明不仅语法是非常重要的,但这些性状的排序也扮演着什么角色。我在Jason Swartz的Learning Scala(第177页)中找到了相当启发的解释。

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

  • 在此背景下,扩大与相同的字段名多性状会出错,一模一样的“,如果你是扩展一个类,并提供自己的方法的版本,但没有添加替代关键字” 。

由于它决定了继承树的形状,所以线性化顺序的确是一个非常重要的问题。举例来说,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 

这很好地反映了线性继承图的结构。