1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
trait A { val audience: String println("Hello " + audience) } class BMember(a: String = "World") extends A { val audience = a println("I repeat: Hello " + audience) } class BConstructor(val audience: String = "World") extends A { println("I repeat: Hello " + audience) } new BMember("Readers") new BConstructor("Readers") |
Данный код выведет следующий результат:
Hello null
I repeat: Hello Readers
Hello Readers
I repeat: Hello Readers
Такое поведение объясняться следующим: при создании дочернего элемента от супер класса или трейта, родительский конструктор будет выполнен перед первой строкой дочернего конструктора, но только после завершения объявления класса. Иначе говоря присвоение в поле трейта audience выполняется в классе BMember, уже внутри конструктора, а значит что родительский код сработает до присвоения и выведет на экран значение пол умолчанию для поля (это null). Во втором случае присвоение полю находиться внутри описания класса, которое сработает перед вызовом родительского конструктора, и мы получим нормальный ожидаемый вывод.