是的,这被称为"线性化",它以一种非常聪明的方式解决了多重继承中令人讨厌的菱形问题。
查看链接(或原始论文),你将比我能给出的任何快速答案更多地了解到这个问题,但基本思想是:从多个特征或抽象类继承的顺序很重要。Scala将创建一个单一的继承线,没有断层,通过按顺序选择父级并调用最接近的覆盖。
或者更好的是,查看《Scala编程》第一版第12章的经典示例:
Scala的线性化主要特性可以通过以下示例进行说明:假设您有一个名为Cat的类,它继承自一个超类Animal和两个trait Furry和FourLegged。 FourLegged又扩展了另一个trait HasLegs。
class Animal
trait Furry extends Animal
trait HasLegs extends Animal
trait FourLegged extends HasLegs
class Cat extends Animal with Furry with FourLegged
Class Cat的继承层次结构和线性化如图12.1所示。继承使用传统的UML符号表示:
3 白色三角箭头的箭头表示继承,箭头指向超类型。黑色非三角箭头的箭头描绘了线性化。黑色箭头指向超级调用将被解决的方向。
![image images/linearization.jpg](https://istack.dev59.com/sRABC.webp)
图12.1 - 类Cat的继承层次和线性化。
Cat的线性化从后往前计算,最后一部分是其父类Animal的线性化。这个线性化被复制并保持不变。(这些类型的线性化在此处的表12.1中显示。) 因为Animal没有显式地扩展任何超类或混合任何超特征,所以默认情况下它扩展了AnyRef,而AnyRef又扩展了Any。因此,Animal的线性化看起来像:
![image images/AnimalLine.jpg](https://istack.dev59.com/iHbyz.webp)
倒数第二部分是对第一个mixin,即Furry特质的线性化,但所有已经在Animal线性化中的类现在都被排除在外,这样每个类在Cat的线性化中只出现一次。结果如下:
![image images/FurryLine.jpg](https://istack.dev59.com/4lAN0.webp)
这是在 FourLegged 的线性化之前进行的,其中任何已经在超类或第一个 mixin 的线性化中被复制的类都会被省略:
![image images/FourLeggedLine.jpg](https://istack.dev59.com/BF49J.webp)
最后,在Cat的线性化中,第一个类就是Cat本身:
![image images/CatLine.jpg](https://istack.dev59.com/452ut.webp)
当这些类和特征中的任何一个通过super调用方法时,被调用的实现将是线性化中其右侧的第一个实现。
class Cat extends Animal with Furry with FourLegged
改为class Cat extends Animal with FourLegged with Furry
,这会改变什么吗? - TheMPcat --> Furry --> FourLegged --> HasLegs --> Animal --> AnyRef --> Any
。注意顺序被反转了吗?在决定重写方法调用时,这很重要。特别是,请阅读第12章的“可堆叠修改”部分。 - Daniel Langdon