Is there something wrong with an abstract value us

2019-03-23 07:27发布

问题:

I have

trait Invoker {
  val method: Method
}

Intellij IDEA code inspection is warning me that "Abstract value used in trait". Everything compiles fine. Is there something wrong with having an abstract value in a trait? If so, how should I specify that all extenders of the trait must define a method property?

回答1:

What is meant by this is the following weirdness:

trait A {
  val i: String
  def j: String
}

class C extends A {
  println ("val i = " + i)
  println ("def j = " + j)

  val i = "i"
  def j = "j"
}

val c = new C
// prints
// val i = null
// def j = j

So, as you can see i is initialised to it default value (null for AnyRef) before it is finally overridden by the constructor in C. (def declarations are re-referenced immediately.)

To avoid this one would have to put the val initialisations to the beginning of the constructor, if possible.


Additional weirdness (and how to solve it) in the following case

Consider

trait A {
  val i: String
  def j: String
}

abstract class D extends A {
  println ("val i = " + i)
  println ("def j = " + j)
}

class C extends D {
  val i = "i"
  def j = "j"
}
val c = new C
// prints
// val i = null
// def j = null

Now we seem to be out of luck; it looks as if there is no chance for us to initialise val i and def j before our superclass D tries to print them. In order to solve this problem, we must use Early definitions (§5.1.6 Scala reference):

class C extends {
  val i = "i"
  def j = "j"
} with D

val c = new C
// prints
// val i = i
// def j = j

And it works!



回答2:

There are plenty of good reasons to use an abstract val in a trait. Unfortunately, IntelliJ IDEA does not distinguish those and simply warns against their use universally. In practice, this means that IntelliJ IDEA warnings are ignored.



标签: scala traits