Scala 特质线性化
Scala线性化 是一个确定的过程,当创建一个使用不同特质和类的继承来定义的类的对象时,它就会发挥作用。线性化有助于解决钻石问题,当一个类或特质从两个不同的具体类或特质中继承相同的属性时,就会出现钻石问题。
语法:
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
这里 Any 是所有类的超类,也叫顶类。它定义了某些通用方法,如equals、hashCode和toString。 AnyRef 代表引用类。所有非值类型都被定义为引用类型。AnyRef对应的是java.lang.object。每一个Scala trait和类都在线性化层次结构的末端隐式地扩展这些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 car1 = new new_Car
println(car1.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 Myflavour2 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 icecream1 = new Myflavour
var icecream2 = new Myflavour2 with jelly
println(icecream1.make("chocolate "))
println(icecream2.make("vanilla "))
}
}
输出:
chocolate with jelly texture
()
vanilla with jelly in cone with cream texture
()
关于线性化的重要观点
- Scala通过线性化过程解决了特质/类的模糊性。
- 每当一个新类被实例化时,Scala都会使用线性化。将所有的特质/类形成一个线性顺序,指向相应的超类/特质,从而 使超 方法知道其父方法。
- 这些超级方法的调用是以一种可堆叠的方式进行的。
- 线性化可能与继承的混杂物的写法相同,也可能不相同。
- 当一个类在线性化中已经被隐式继承时,我们不能明确地将其添加到继承中,否则会导致 两次继承的 错误 。
- 在线性化中没有特质/类是重复的。