Scala的特征线性化详细指南

2021年3月27日13:58:11 发表评论 849 次浏览

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的特征线性化1

特性线性化和继承图

正如我们在上图中所看到的, 线性化将与继承的结构不同。 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 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可能相同或不同。
  • 当一个类已经被线性化隐式继承时, 我们不能为继承显式添加一个类, 否则会导致错误继承两次.
  • 线性化中不会重复任何特征/类。

木子山

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: