Sorry for the broad topic; I'm just not quite sure what I'm doing wrong.
I have a class structure
trait BaseType {
val property: String
}
trait MiddleTrait extends BaseType {
val myProperty = property.length.toString
def userProperty() = {
myProperty
}
}
object Top extends MiddleTrait {
val property = "value given here"
} trait BaseType {
val property: String
}
Which compiles; but hits a run time error - java.lang.RuntimeException: java.lang.NoClassDefFoundError: Could not initialize class controllers.test.Top$
Updating MiddleTrait to **def** myProperty = property.length.toString
it will run fine.
I looking to understand the theory behind this better so I could predict the error without seeing it fail at run time first
Thanks
--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-user+...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
--
It's been a while since we heard from the Urfaq,
On local access cable tv they're still running ads for -Xcheckinit.
On Mon, May 25, 2015, 7:08 AM Jon Pretty <prope...@gmail.com> wrote:
Hi Brent,
Just to elaborate on Martin's answer, the problem is that the body of `Top`, which contains the concrete implementation of `val property` is evaluated *after* the body of `MiddleTrait` which eagerly evaluates `val myProperty`, whose body depends on `property`, and we can see, deterministically, that it will always fail because these two values need to be evaluated in the reverse order.
You can "fix" this by ensuring that `property` is initialized *before* the body of MiddleTrait by writing `Top` as follows:
object Top extends { val property = "value given here" } with MiddleTrait
This feature of Scala is called "early initializers" (they're the name of the *solution*, rather than the problem - though arguably the name could refer to the problem too...), but they are normally best avoided, which you can usually do with more careful inheritance, or using `def`s (as you found out) or `lazy val`s (which don't result in the re-evaluation of the implementation every time it's accessed). Dotty will not have early initializers.
...since it will give traits value parameters, which avoid the problem, no?
...since it will give traits value parameters, which avoid the problem, no?