Scala初始化行为

时间:2010-09-30 12:07:48

标签: scala initialization traits

请查看以下代码。

trait MyTrait { val myVal : String }

class MyClass extends MyTrait { val myVal = "Value" }

class MyClass2(val myVal: String) extends MyTrait 

为什么MyClassMyClass2的初始化顺序不同? MyClass的构造函数将为

MyClass() {
  MyTrait$class.$init$(this);
  myVal = value
}

MyClass2的构造函数将是

MyClass2(String myVal) { this.myVal = myVal; MyTrait$class.$init$(this) }

我认为初始化顺序应该是MyClass2的构造函数,两种情况都是一样的。

1 个答案:

答案 0 :(得分:23)

Scala specification的第5.1节末尾,定义了以下内容:

  

模板评估。考虑模板 sc mt 1 mt   n {stats} 。如果这是模板   特征(§5.3.3)然后是它   mixin-evaluation由一个评估组成   语句序列的使用   统计。如果这不是a的模板   特质,然后它的评价包括   以下步骤。

     
      
  • 首先,评估超类构造函数sc(第5.1.1节)。
  •   
  • 然后,模板线性化(第5.1.2节)中的所有基类向上   到模板的超类表示   通过sc进行混合评估。   Mixin评估反过来发生   发生的顺序   线性化。
  •   
  • 最后评估语句序列统计信息。
  •   

但是,请注意,构造函数参数可以由跟随它的任何构造函数使用。因此,需要在它们之前进行初始化。这在第5.1.1节末尾明确说明:

  

构造函数的评估   调用 x.c targs。 。   。(argsn)由以下内容组成   步骤进行:

     
      
  • 首先,评估前缀 x
  •   
  • 然后,参数 args1 ,. 。 。 ,argsn 从左到右进行评估   右。
  •   
  • 最后,正在构建的类通过评估来初始化   所引用的类的模板    C
  •   

这对您没有任何问题,但您最近执行的 {stats} 确实存在问题。 {stats} 最后执行的原因是它可能引用其祖先类和特征的属性,而祖先显然不知道它的后代。因此,在 {stats} 执行之前,需要完全初始化祖先。

当然, 可能需要提前初始化。第5.1.6节:早期定义涵盖了这一点。这是你写的方式:

class MyClass extends { val myVal = "Value" } with MyTrait