覆盖属性的行为与scala中的方法

时间:2017-06-11 22:28:25

标签: scala

让我们定义最简单的继承:

class A           {          val base: String = { println("a hello"); "hello" } }
class B extends A { override val base: String = { println("b hi"); "B hello"} }

现在让我们尝试一下:

scala> new B().base
a hello
b hi
res0: String = B hello

那么......很多(/大多数?)你们可能不会对此感到惊讶。 。我的(错误的......)假设B.base 完全 覆盖A.base。相反,我们会看到两个* 方法被调用:基本方法A.base然后覆盖方法B.base

好的那么..为了避免这种双倍行为,val必须转换为def(方法),这是真的吗?

class A           {          def base: String = { println("a hello"); "hello" } }
class B extends A { override def base: String = { println("b hi"); "B hello"} }

现在我们有了理想的行为:

scala> new B().base
b hi
res1: String = B hello

鉴于这种情况:什么时候覆盖val在一个类的主体中有用?

2 个答案:

答案 0 :(得分:1)

  

我的(错误的......)假设B.base将完全覆盖A.base。相反,我们看到两个方法都被调用:基本方法A.base然后覆盖方法B.base。

不,我们没有。 printlnA.base中的B.base次调用在构造函数中发生,而不是在您访问base时。这就是(非lazy)成员val的含义:右侧是在构造函数和结果中执行的(在您的案例中只是"hello""B hello" )存储在一个字段中。访问base只会返回该字段的值。

超类构造函数总是在子类构造函数之前完全执行,没有办法覆盖它(你可以覆盖它调用的任何方法,但是你需要小心所以它们不依赖于子类'尚未初始化的状态'。

scala> val b = new B()
a hello
b hi
scala> b.base
res0: String = B hello
  

什么时候覆盖val在类的主体中有用?

当您希望子类“val具有不同的值时”。

答案 1 :(得分:0)

LAZY val

它来找我..

class A           {          lazy val base: String = { println("a hello"); "hello" } }
class B extends A { override lazy val base: String = { println("b hi"); "B hello"} }

现在我们得到预期的行为:

scala> new B().base
b hi
res1: String = B hello