Scala initialization behaviour

前端 未结 1 1378
迷失自我
迷失自我 2021-02-05 12:30

Please look at the following code.

trait MyTrait { val myVal : String }

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

class MyClass2(val myVal: Strin         


        
相关标签:
1条回答
  • 2021-02-05 12:58

    At the end of section 5.1 of the Scala specification, the following is defined:

    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.

    • 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.

    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:

    An evaluation of a constructor invocation x.c targs. . .(argsn) consists of the following steps:

    • 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.

    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.

    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
    
    0 讨论(0)
提交回复
热议问题