【Scala谜题】成员声明的位置

笔记来源:
Scala谜题

在许多面向对象的语言中,常常在类构造器中接受参数,目的是将参数赋值给类成员。

执行下面的代码会是什么结果呢?

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

通常,BConstructor 中的模式是首选的,因为它的行为更少可能会引起意外。这时,超类中声明的 val 绝不会存在于非初始化的状态。

其实,超类和超特质初始化代码的执行是在参数评估和早期字段定义之后,实例化类和特质的初始化语句之前。直接超类和混进特质是当它们出现在 classtraitobject 定义中时按从左到右的顺序初始化。

因此,考虑以下初始化方式:

class BMember2(a: String = "World") extends {
  val audience = a
} with A {
  println("I repeat: Hello " + audience)
}
new BMember2("Readers")

它的输出结果则为:

Hello Readers
I repeat:Hello Readers

实际生产中,最好考虑在类或对象体的括号后(这是主构造器)按照从左到右的声明顺序插入超类构造器和超特质初始化程序。

    原文作者:gcusky
    原文地址: https://segmentfault.com/a/1190000014615591
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞