Avoid the overridden `val` initialized in the base trait?
In the following code:
trait Base {
val foo: String = {
println("Hi, I'm initializing foo in trait Base")
"foo"
}
}
class Overrider extends Base {
override val foo = "bar!"
}
object Runner extends App {
println(new Overrider().foo)
println((new {override val foo = "baz"} with Base).foo)
}
Base
The value foo
initialization of the value is called regardless of whether I override the value val by expanding the attribute or using an early initializer:
Hi, I'm initializing foo in trait Base
bar!
Hi, I'm initializing foo in trait Base
baz
Is there a way to use val
and avoid this, or should I just stick with lazy val
s?
source to share
Use either lazy val
, as you mentioned, or def
. AFAIK there is no other way to avoid initialization val
in base classes. This is due to the fact that all external definitions of class members go into the constructor. Therefore, it val
will be initialized by build time.
Another approach would be to define the interface from which you are propagating:
trait Base {
def foo: String
}
class Foo extends Base {
override val foo = "foo"
}
class Bar extends Base {
override val foo = "bar"
}
source to share
Since other users have answered your question, you must define foo
how def
if you do not want the evaluated method to be Base
evaluated.
You told me in the comments to your question that you were trying to implement the wiring module as described in this link . Then you try to implement the thin cake pattern .
In this case, it is logically incorrect to declare foo
as val
. foo
is an addiction that cannot be eagerly resolved. If you use val
, these two components will be closely related. You must define foo
how def
to allow your main application (or testing) to connect foo
to the correct type, i.e. A specific class or layout.
Let me know if you want more explanation.
source to share