2010-09-30 3 views
15

Пожалуйста, ознакомьтесь со следующим кодом.Действия инициализации Scala

trait MyTrait { val myVal : String } 

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

class MyClass2(val myVal: String) extends MyTrait 

Почему порядок инициализации отличаются в случае MyClass и MyClass2? Конструктор MyClass будет как

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

Конструктор MyClass2 будет

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

Я думаю, что порядок инициализации должен быть MyClass2 «s конструктор делает, то же самое для обоих случаев.

ответ

23

В конце раздела 5.1 Scala specification следующее определяется:

шаблона оценки. Рассмотрим шаблон подкожно с мт 1 с т п {} статистики. Если это шаблон признак (§5.3.3), то его оценка включает в себя оценку состояния . Если это не шаблон признака , то его оценка состоит из следующих шагов.

  • Во-первых, вычисляется конструктор sc суперкласса sc (§5.1.1).
  • Затем все базовые классы в линеаризации шаблона (§5.1.2) вверх к суперклассу шаблона, обозначенному sc оцениваются по методу mixin. Оценка миксинов в обратном порядке порядок возникновения в линеаризации .
  • Оценка статистики последовательности выводов.

Однако следует отметить, что параметры конструктора могут быть использованы любыми конструкторами, которые следуют за ним. Поэтому перед этим необходимо выполнить инициализацию. Это сделано явно в конце раздела 5.1.1:

Оценка конструктор вызов x.c targs. , . (argsn) состоит из следующих шагов :

  • Во-первых, префикс х оценивается.
  • Затем аргументы args1,. , , , argsn оцениваются слева направо на .
  • И наконец, создаваемый класс инициализируется путем оценки шаблона класса, на который ссылаются c.

Это у вас нет никаких проблем с, но у вас есть проблемы с {} Статистика запущенную в прошлом. Причина, по которой {stats} выполнена последним, заключается в том, что она может ссылаться на атрибуты ее классов и свойств предков, тогда как предки, очевидно, не знают о своих потомках. Следовательно, предки должны быть полностью инициализированы до того, как будет выполнен {stats}.

Конечно, возможно, что вам do нужна ранняя инициализация. Об этом говорится в разделе 5.1.6: «Ранние определения». Вот как вы его напишете:

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

В конце концов я видел причину, по которой Scala инициализирует объект в этом порядке. Спасибо за ответ, Дэниел. – Dmitry

Смежные вопросы