Scala中多种性状的混合
快速说明:教程中的示例 假设我有学生、工人、低收入和年轻的特点 我如何才能声明一个类(而不是实例),一个大学生,具有所有这些特征 注:我知道最简单的情况,例如有一个或两个特征的大学生:Scala中多种性状的混合,scala,mixins,traits,Scala,Mixins,Traits,快速说明:教程中的示例 假设我有学生、工人、低收入和年轻的特点 我如何才能声明一个类(而不是实例),一个大学生,具有所有这些特征 注:我知道最简单的情况,例如有一个或两个特征的大学生: class CollegeStudent extends Student with Worker 这很简单,当声明一个类时,您只需根据需要经常使用“with”关键字 class CollegeStudent extends Student with Worker with Underpaid with Youn
class CollegeStudent extends Student with Worker
这很简单,当声明一个类时,您只需根据需要经常使用“with”关键字
class CollegeStudent extends Student with Worker with Underpaid with Young
如果某个特性改变了类的行为,那么特性的顺序可能很重要,这完全取决于您使用的特性
此外,如果您不想拥有一个始终使用相同特征的类,您可以稍后使用它们:
class CollegeStudent extends Student
new CollegeStudent with Worker with Underpaid with NotSoYoungAnymore
我认为非常重要的是,不仅要解释语法,还要解释特征的顺序扮演着什么角色。我发现杰森·斯沃茨(第177页)的解释很有启发性
- Scala类可以一次扩展多个trait,但JVM类只能扩展一个父类。Scala编译器通过创建“每个特征的副本以形成一个高的、单列的特征层次结构”来解决这个问题 “类别和特征”,这是一个称为线性化的过程
- 在这种情况下,扩展具有相同字段名的多个trait将无法编译,这与“扩展类并提供自己的方法版本但未能添加覆盖关键字”完全相同
类D用B和C扩展了A(其中A是类,B是类)
C是特征)将变成类D扩展C扩展B扩展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 }
调用newd()
将使REPL打印以下内容:
D->C->B->A->Base
它完美地反映了线性化遗传图的结构。改变行为意味着调用一个在多个trait中实现并具有相同名称的trait方法。因此,根据特征的顺序,它将调用该方法。