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?

+3


source to share


2 answers


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"
}

      

+3


source


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.

0


source







All Articles