Scala 中的线性化顺序 [英] Linearization order in Scala

查看:47
本文介绍了Scala 中的线性化顺序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在处理 trait 时,我很难理解 Scala 中的线性化顺序:

I have difficulties in understanding the linearization order in Scala when working with traits:

class A {
  def foo() = "A"
}

trait B extends A {
  override def foo() = "B" + super.foo()
}

trait C extends B {
  override def foo() = "C" + super.foo()
}

trait D extends A {
  override def foo() = "D" + super.foo()
}

object LinearizationPlayground {
    def main(args: Array[String]) {

      var d = new A with D with C with B;
      println(d.foo) // CBDA????
  }    
}

它打印 CBDA 但我不知道为什么.性状的顺序是如何确定的?

It prints CBDA but I can't figure out why. How is the order of the traits determined?

谢谢

推荐答案

推理线性化的一种直观方法是参考构造顺序并可视化线性层次结构.

An intuitive way to reason about linearisation is to refer to the construction order and to visualise the linear hierarchy.

你可以这样想.首先构造基类;但是在能够构造基类之前,必须首先构造它的超类/特征(这意味着构造从层次结构的顶部开始).对于层次结构中的每个类,混合特征是从左到右构造的,因为右侧的特征是稍后"添加的,因此有机会覆盖"之前的特征.但是,与类类似,为了构造特征,必须首先构造其基本特征(显而易见);并且,相当合理的是,如果一个特征已经被构建(在层次结构中的任何地方),它就不会被再次构建.现在,构造顺序与线性化相反.认为基本"特征/类在线性层次结构中较高,而层次结构中较低的特征则更接近作为线性化主题的类/对象.线性化会影响特征中super"的解析方式:它将解析为最接近的基本特征(在层次结构中较高).

You could think this way. The base class is constructed first; but before being able of constructing the base class, its superclasses/traits must be constructed first (this means construction starts at the top of the hierarchy). For each class in the hierarchy, mixed-in traits are constructed left-to-right because a trait on the right is added "later" and thus has the chance to "override" the previous traits. However, similarly to classes, in order to construct a trait, its base traits must be constructed first (obvious); and, quite reasonably, if a trait has already been constructed (anywhere in the hierarchy), it is not reconstructed again. Now, the construction order is the reverse of the linearisation. Think of "base" traits/classes as higher in the linear hierarchy, and traits lower in the hierarchy as closer to the class/object which is the subject of the linearisation. The linearisation affects how `super´ is resolved in a trait: it will resolve to the closest base trait (higher in the hierarchy).

因此:

var d = new A with D with C with B;

A with D with C with B 的线性化是

  • (层次结构的顶部)A(首先构造为基类)
  • D 的线性化
    • A(不视为 A 出现在之前)
    • D(D 扩展 A)
    • A(不视为 A 出现在之前)
    • B(B 扩展 A)
    • C(C 扩展 B)
    • A(不视为 A 出现在之前)
    • B(不认为 B 出现在之前)

    所以线性化是:A-D-B-C.您可以将其视为线性层次结构,其中 A 是根(最高)并首先构造,而 C 是叶(最低)并最后构造.由于 C 是最后构造的,这意味着可能会覆盖以前的"成员.

    So the linearization is: A-D-B-C. You could think of it as a linear hierarchy where A is the root (highest) and is constructed first, and C is the leaf (lowest) and constructed last. As C is constructed last, it means that may override "previous" members.

    根据这些直观的规则,d.foo 调用 C.foo,它返回一个 "C" 后跟 super.foo()它在 B 上解析(B 左边的特征,即在线性化中更高/之前),它返回一个 "B" 后跟 super.foo()D 上解析,它返回一个 "D" 后跟在 A<上解析的 super.foo()/code>,最终返回A".所以你有CBDA".

    Given these intuitive rules, d.foo calls C.foo, which returns a "C" followed by super.foo() which is resolved on B (the trait on the left of B, i.e. higher/before, in the linearization), which returns a "B" followed by super.foo() which is resolved on D, which returns a "D" followed by super.foo() which is resolved on A, which finally returns "A". So you have "CBDA".

    作为另一个例子,我准备了以下内容:

    As another example, I prepared the following one:

    class X { print("X") }
    class A extends X { print("A") }
    trait H { print("H") }
    trait S extends H { print("S") }
    trait R { print("R") }
    trait T extends R with H { print("T") }
    class B extends A with T with S { print("B") }
    
    new B  // X A R H T S B     (the prints follow the construction order)
    
    // Linearization is the reverse of the construction order.
    // Note: the rightmost "H" wins (traits are not re-constructed)
    // lin(B) = B >> lin(S) >> lin(T) >> lin(A)
    //        = B >> (S >> H) >> (T >> H >> R) >> (A >> X)
    //        = B >> S >> T >> H >> R >> A >> X
    

    这篇关于Scala 中的线性化顺序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆