我正在通过Scala的Odersky编程进行工作,并且正在查看有关特征的章节。他举了一个示例,其中将各种特征/类线性化并说:
Cat -> FourLegged -> HasLegs -> Furry -> Animal -> AnyRef -> Any
当这些类和特征中的任何一个通过super调用方法时, 调用的实现将是其右侧的第一个实现 线性化。
我对类/特征的定义如下:
abstract class Animal { def hi }
class Cat extends Animal { def hi { println("cat") } }
trait Furry extends Animal { abstract override def hi {
println("furry"); super.hi } }
完成
val c = new Cat with Furry
c.hi
我明白了
furry
cat
根据这本书,毛茸茸的超级人应该调用Animal.hi
,因为Animal是抽象的,因此应该会导致编译错误或运行时错误。相反,它调用cat.hi
我想念什么?我以为Cat类会在线性化过程中首先出现,因此super
调用无法调用它吗?
(为了简化起见,我错过了HasLegs和FourLegged)
我怀疑他们误解了线性化顺序?
谢谢!
编辑:在下面user2357112的评论之后,我尝试静态混合Furry特性:
scala> class Cat extends Animal with Furry { def hi { println("cat") } }
<console>:13: error: overriding method hi in trait Furry of type => Unit;
method hi needs `override' modifier
class Cat extends Animal with Furry { def hi { println("cat") } }
我现在很困惑,因为我认为无论是在运行时还是在代码中混入特质都没有什么不同。但是在这里,运行时mixin的执行没有错误,但是如果尝试将其混入代码中,则会出现编译错误。是什么赋予了?
答案 0 :(得分:0)
根据this answer,使用mixin时将首先构造具体类,而线性化顺序与构造顺序相反。因此,构造为Animal -> Cat -> Furry
,线性化为Furry -> Cat -> Animal
,这就是为什么您首先看到“毛茸茸”而第二看到“猫”的原因。