在Scala中混合多个特征

时间:2009-07-05 18:23:00

标签: scala mixins traits

快速说明:教程中的示例 Scala for Java Refugees Part 5: Traits and Types

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

我如何宣布具有所有这些特征的类(非实例),CollegeStudent?

注意:我知道简单的案例,例如有一两个特征的CollegeStudent:

class CollegeStudent extends Student with Worker

2 个答案:

答案 0 :(得分:96)

很容易,在声明课程时,你只需要经常使用“with”关键字

class CollegeStudent extends Student with Worker with Underpaid with Young

如果特征改变了阶级的行为,特征的顺序可能很重要,这一切都取决于你正在使用的特征。

此外,如果你不想让一个总是使用相同特征的类,你可以在以后使用它们:

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

答案 1 :(得分:9)

我认为不仅要解释语法非常重要,而且还要解释特征排序的作用。我发现Jason Swartz的Learning Scala(第177页)中的解释非常有启发性。

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

  • 在此上下文中,扩展具有相同字段名称的多个特征将无法编译,完全相同的“,就像您正在扩展类并提供自己的方法版本但未能添加覆盖一样关键字

由于它确定了继承树的形状,线性化顺序确实是一个非常重要的问题。例如,class D extends A with B with C(其中A是类,B 将成为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

这完美地反映了线性化继承图的结构。