Scala 特质线性化

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中的特质线性化

特质线性化和继承图

正如我们在上图中看到的,线性化与继承结构不一样。Scala特质/类是以线性顺序动态放置的,其中线性化将被应用,如下所示。

D-> C-> B-> A-> AnyRef-> Any

以下是确定线性化的规则

  1. 取第一个 扩展 特质/类,以垂直形式写出其完整的继承层次结构,将此层次结构存储为X。
  2. 子句之后取下一个特质/类,写出其完整的层次结构,并取消在层次结构X中重复出现的类或特质,将剩余的特质/类添加到层次结构X的前面。
  3. 转到第2步,重复这个过程,直到没有特质/类被遗漏。
  4. 将类本身放在层次结构的前面,作为编写层次结构的头。

让我们来了解一些例子。

例子:

// 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都会使用线性化。将所有的特质/类形成一个线性顺序,指向相应的超类/特质,从而 使超 方法知道其父方法。
  • 这些超级方法的调用是以一种可堆叠的方式进行的。
  • 线性化可能与继承的混杂物的写法相同,也可能不相同。
  • 当一个类在线性化中已经被隐式继承时,我们不能明确地将其添加到继承中,否则会导致 两次继承的 错误
  • 在线性化中没有特质/类是重复的。

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程