WestCoastProjects
WestCoastProjects

Reputation: 63062

Behavior of overridden attribute vs a method in scala

Let us define simplest inheritance:

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

Now let's try it out:

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

So .. many (/most?) of you out there will likely not be surprised by this. I was . It had been my (incorrect ..) assumption that the B.base would completely override A.base . Instead we see both* methods being invoked : the base method A.base then the overriding method B.base.

Ok then .. so is it true that in order to avoid this doubling-up behavior that the val must be converted to a def (method) ?

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

And now we have the desired behavior:

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

Given this situation: when is overriding val useful within the body of a class?

Upvotes: 1

Views: 64

Answers (2)

Alexey Romanov
Alexey Romanov

Reputation: 170733

It had been my (incorrect ..) assumption that the B.base would completely override A.base . Instead we see both methods being invoked : the base method A.base then the overriding method B.base.

No, we don't. The println calls in both A.base and B.base happen in the constructor, not when you access base. This is just what (non-lazy) member val means: the right-hand side is executed in the constructor and the result (just "hello" or "B hello" in your case) is stored into a field. Accessing base just returns the value of that field.

And superclass constructor is always fully executed before the subclass constructor, there's no way to override it (you can override any methods it invokes, but you need to be careful so they don't rely on subclass' state which isn't initialized yet).

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

when is overriding val useful within the body of a class?

When you want the subclass' val to have a different value, of course.

Upvotes: 1

WestCoastProjects
WestCoastProjects

Reputation: 63062

LAZY val

It came to me ..

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

And now we get expected behavior:

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

Upvotes: 0

Related Questions