Scala初始化行为 [英] Scala initialization behaviour
问题描述
请查看以下代码.
trait MyTrait { val myVal : String }
class MyClass extends MyTrait { val myVal = "Value" }
class MyClass2(val myVal: String) extends MyTrait
在MyClass
和MyClass2
的情况下,为什么初始化顺序不同?
MyClass
的构造函数将为
Why does the initialization order differ in case of MyClass
and MyClass2
?
The constructor of MyClass
will be as
MyClass() {
MyTrait$class.$init$(this);
myVal = value
}
MyClass2
的构造函数将是
MyClass2(String myVal) { this.myVal = myVal; MyTrait$class.$init$(this) }
我认为初始化顺序应该与MyClass2
的构造函数相同,这两种情况都是相同的.
I think the initialization order should be as MyClass2
's constructor does, the same for both cases.
推荐答案
Scala规范,定义如下:
模板评估.考虑模板 sc 具有 mt 1 具有 mt n {stats} .如果这是模板 一个特征(第5.3.3节),然后将其 mixin评估包含一个评估- 语句序列的确定 统计资料.如果这不是模板的模板 特质,则其评估包括 以下步骤.
Template Evaluation. Consider a template sc with mt 1 with mt n {stats}. If this is the template of a trait (§5.3.3) then its mixin-evaluation consists of an eval- uation of the statement sequence stats. If this is not a template of a trait, then its evaluation consists of the following steps.
- 首先,对超类构造函数sc进行评估(第5.1.1节).
- 然后,模板线性化(第5.1.2节)中的所有基类 表示为模板的超类 通过sc进行混合评估. 反向混合素评估 出现顺序 线性化.
- 最后评估语句序列统计信息.
- First, the superclass constructor sc is evaluated (§5.1.1).
- Then, all base classes in the template’s linearization (§5.1.2) up to the template’s superclass denoted by sc are mixin-evaluated. Mixin-evaluation hap- pens in reverse order of occurrence in the linearization.
- Finally the statement sequence stats is evaluated.
但是,请注意,其后的任何构造函数都可以使用构造函数参数.因此,需要在它们之前进行初始化.在第5.1.1节的末尾对此进行了明确说明:
Note, however, that the constructor parameters may be used by any constructors that follow it. Therefore, it needs to be initialized before them. This is made explicit at the end of section 5.1.1:
对构造函数的评估 调用 x.c targs. . .(argsn)由以下内容组成 步骤:
An evaluation of a constructor invocation x.c targs. . .(argsn) consists of the following steps:
- 首先,评估前缀 x .
- 然后,参数 args1,. . . ,argsn 从左到右求值 是的.
- 最后,通过评估 所引用类的模板 c .
- First, the prefix x is evaluated.
- Then, the arguments args1 , . . . , argsn are evaluated from left to right.
- Finally, the class being constructed is initialized by evaluating the template of the class referred to by c.
您没有任何问题,但是您确实有问题,最后执行 {stats} .最后执行 {stats} 的原因是它可以引用其祖先类和特征的属性,而祖先显然不了解其后代.因此,在执行 {stats} 之前,祖先需要完全初始化.
This you don't have any problem with, but you do have a problem with {stats} being executed last. The reason why {stats} is executed last is that it may reference attributes of its ancestor classes and traits, whereas the ancestors obviously have no knowledge about its descendants. Therefore, the ancestors need to be fully initialized before {stats} gets executed.
当然,您可能要做需要尽早初始化.第5.1.6节:早期定义中对此进行了介绍.这是您的写法:
Of course, it is possible that you do need early initialization. This is covered by section 5.1.6: Early Definitions. Here's how you'd write it:
class MyClass extends { val myVal = "Value" } with MyTrait
这篇关于Scala初始化行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!