Scala线性化是一个确定性的过程,当一个类的对象被创建时,它是通过继承不同的特征和类来定义的。线性化有助于解决钻石问题,当一个类或特征从2个不同的具体类或特征继承相同的属性。
语法 :
trait C{}
trait B{}
class A{}
object a_obj= new class A extends B with C
线性化如下所示:-
C-> AnyRef-> Any
B-> AnyRef-> Any
A-> AnyRef-> Any
a_obj-> A-> C-> B-> AnyRef-> Any
这里任何是所有类的超类, 也称为顶级类。它定义了某些通用方法, 例如equals, hashCode和toString。任何参考代表参考类别。所有非值类型都定义为引用类型。 AnyRef对应于java.lang.object。每个Scala特征和类在线性化层次结构的末尾隐式扩展了这些Scala对象。
例子 :
// Scala program defining trait A
trait A
{
def name : String
}
// defining trait B inheriting A
trait B extends A
{
override def name : String = "class b"
}
// defining trait C inheriting A
trait C extends A
{
override def name : String = "class c"
}
// defining class D inheriting B and C both
class D extends B with C
{
override def name : String = super .name
}
// Creating object
object GFG
{
// Main method
def main(args : Array[String])
{
var class _ d = new D
// whose property will be inherited
println(class _ d.name)
}
}
输出:
class c
线性化D类跟随深色的黑体箭头。遗产D类跟随着轻箭头。
特性线性化和继承图
正如我们在上图中所看到的, 线性化将与继承的结构不同。 Scala特征/类以线性顺序动态放置, 线性化将按以下方式应用。
D-> C-> B-> A-> AnyRef-> Any
遵循以下规则来确定线性化:
- 先走扩展的特征/类, 并以垂直形式写入其完整的继承层次结构, 将此层次结构存储为X。
- 在与子句, 编写其完整的层次结构并取消在层次结构X中重复的类或特征。将其余的特征/类添加到层次结构X的前面。
- 转到步骤2并重复该过程, 直到没有任何特征/类别。
- 将类本身放置在层次结构的前面, 作为要为其编写层次结构的标题。
让我们了解一些示例。
范例:
// Scala program for linearization
// defining old_car class
class old _ Car
{
def method : String = "old car "
}
// defining new_Car_Designs trait
trait new _ Car _ Designs extends old _ Car
{
override def method : String = "Designing-> " + super .method
}
// defining new_Car_Part trait
trait new _ Car _ Part extends old _ Car
{
override def method : String = "Add new part-> " + super .method
}
// defining new_Car_Paint trait
trait new _ Car _ Paint extends old _ Car
{
override def method : String = "Repainting-> " + super .method
}
// defining new_Car class
class new _ Car extends new _ Car _ Paint with
new _ Car _ Part with new _ Car _ Designs
{
override def method : String = "new car-> " + super .method
}
// Creating object
object geekforgeeks
{
// Main method
def main(args : Array[String])
{
// new_Car object
var car 1 = new new _ Car
println(car 1 .method)
}
}
输出:
new car-> Designing-> Add new part-> Repainting-> old car
范例:
// Scala program for trait linearization
// defining classes and traits
class flavour
{
def make (flavour : String) : Unit =
{
println(flavour)
}
}
// defining texture trait
trait texture extends flavour
{
abstract override def make (flavour : String)
{
super .make(flavour + "texture " )
}
}
// defining cream trait
trait cream extends texture
{
abstract override def make (flavour : String)
{
super .make(flavour + "with cream " )
}
}
// defining jelly trait
trait jelly extends texture
{
abstract override def make (flavour : String)
{
super .make(flavour + "with jelly " )
}
}
// defining cone trait
trait cone extends flavour
{
abstract override def make (flavour : String)
{
super .make(flavour + "in cone " )
}
}
// creating new ice-cream flovours
// with above traits and classes
// inheriting different traits and classes
class Myflavour extends flavour with jelly
{
override def make (flavour : String)
{
super .make(flavour)
}
}
class Myflavour 2 extends flavour with cream with cone
{
override def make (flavour : String)
{
super .make(flavour)
}
}
// Creating object
object GFG
{
// Main method
def main(args : Array[String])
{
// creating new objects
var icecream 1 = new Myflavour
var icecream 2 = new Myflavour 2 with jelly
println(icecream 1 .make( "chocolate " ))
println(icecream 2 .make( "vanilla " ))
}
}
输出:
chocolate with jelly texture
()
vanilla with jelly in cone with cream texture
()
关于线性化的要点
- Scala通过线性化过程解决了特征/类的歧义。
- 每当实例化一个新类时, Scala都会使用线性化。取所有特征/类并形成一个线性顺序, 指向相应的超级类/特征超方法知道其父方法。
- 这些超级方法调用以可堆叠方式完成。
- 线性化与编写它们时继承的mixin可能相同或不同。
- 当一个类已经被线性化隐式继承时, 我们不能为继承显式添加一个类, 否则会导致错误继承两次.
- 线性化中不会重复任何特征/类。