在 Scala 中混合多个特征
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1084572/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Mixing multiple traits in Scala
提问by Daniel Ribeiro
Quick note: Examples from the tutorial Scala for Java Refugees Part 5: Traits and Types.
快速说明:来自Scala for Java Refugees教程第 5 部分:特征和类型的示例。
Suppose I have the traits Student, Worker, Underpaid, and Young.
假设我有学生、工人、低薪和年轻的特征。
How could I declare a class (not instance), CollegeStudent, with all these traits?
我怎么能声明一个类(不是实例),CollegeStudent,具有所有这些特征?
Note:I am aware of the simplests cases, such as CollegeStudent with one or two Traits:
注意:我知道最简单的情况,例如具有一两个特征的 CollegeStudent:
class CollegeStudent extends Student with Worker
回答by Alexander Stolz
It is easy, when declaring a class you just use the "with" keyword as often as you want
这很容易,在声明一个类时,您只需根据需要使用“with”关键字
class CollegeStudent extends Student with Worker with Underpaid with Young
the order of the traits can be important if a trait is changing the behavior of the class, it all depends on traits you are using.
如果特征改变了类的行为,特征的顺序可能很重要,这完全取决于您使用的特征。
Also if you don't want to have a class which always uses the same traits you can use them later:
此外,如果您不想拥有一个总是使用相同特征的类,您可以稍后使用它们:
class CollegeStudent extends Student
new CollegeStudent with Worker with Underpaid with NotSoYoungAnymore
回答by fr_andres
I think that it is very important to explain not only the syntax, but also which role does the ordering of the traits play. I found the explanation in Jason Swartz's Learning Scala(page 177) quite enlightning.
我认为不仅要解释语法,还要解释特征的排序起到什么作用,这一点非常重要。我发现 Jason Swartz 的Learning Scala(第 177 页)中的解释非常有启发性。
A Scala class can extend multiple traits at once, but JVM classes can extend only one parent class. The Scala compiler solves this by creating "copies of each trait to form a tall, single-column hierarchy of the class and traits", a process known as linearization.
In this context, extending multiple traits with identical field names would fail to compile, exactly the same "as if you were extending a class and providing your own version of a method but failed to add an override keyword".
一个 Scala 类可以一次扩展多个特征,但 JVM 类只能扩展一个父类。Scala 编译器通过创建“每个特征的副本以形成类和特征的高单列层次结构”来解决这个问题,这一过程称为线性化。
在这种情况下,扩展具有相同字段名称的多个特征将无法编译,这与“就好像您正在扩展一个类并提供您自己的方法版本但未能添加覆盖关键字一样”。
And since it determines the shape of the inheritance tree, the linearization order is indeed one very important question to regard. As an example, class D extends A with B with C(where A is a class and B
and C are traits) would become class D extends C extends B extends A. The following few lines, also from the book, illustrate that perfectly:
并且由于它决定了继承树的形状,因此线性化顺序确实是一个非常重要的问题。例如,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 }
A call to new D()would have the REPL print the following:
调用new D()将使 REPL 打印以下内容:
D->C->B->A->Base
Which perfectly reflects the structure of the linearized inheritance graph.
完美体现了线性化继承图的结构。

