繁体   English   中英

Scala初始化行为

[英]Scala initialization behaviour

请查看以下代码。

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将是

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

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

Scala规范的 5.1节末尾,定义了以下内容:

模板评估。 考虑 MT 1亿吨N {}统计模板SC。 如果这是特征的模板(第5.3.3节),那么它的mixin评估包括对语句序列统计的评估。 如果这不是特征的模板,则其评估包括以下步骤。

  • 首先,评估超类构造函数sc(第5.1.1节)。
  • 然后,模板线性化(第5.1.2节)中的所有基类直到由sc表示的模板的超类进行混合评估。 混合评估在线性化中以相反的顺序发生。
  • 最后评估语句序列统计。

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

对构造函数调用xc targs的评估 。(argsn)包括以下步骤:

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

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

当然,这是可能的,你确实需要早期初始化。 第5.1.6节:早期定义涵盖了这一点。 这是你如何写它:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM