Подтвердить что ты не робот

Что-то не так с абстрактным значением, используемым в признаке в scala?

У меня

trait Invoker {
  val method: Method
}

Проверка Intellij IDEA предупреждает меня, что "Абстрактное значение используется в признаке". Все прекрасно компилируется. Что-то не так с абстрактным значением в признаке? Если да, то как я должен указать, что все расширители признака должны определять свойство метода?

4b9b3361

Ответ 1

Под этим подразумевается следующая странность:

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

Итак, как вы видите, i инициализируется значением по умолчанию (null для AnyRef), прежде чем он будет переопределен конструктором в C. (def объявления немедленно перенаправляются.)

Чтобы избежать этого, нужно было бы поместить инициализацию val в начало конструктора, если это возможно.


Дополнительная странность (и как ее решить) в следующем случае

Рассмотрим

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

Теперь нам не повезло; похоже, что у нас нет возможности инициализировать val i и def j, прежде чем наш суперкласс D попытается напечатать их. Чтобы решить эту проблему, мы должны использовать ранние определения (§5.1.6 Scala ссылка):

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

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

И он работает!

Ответ 2

Существует множество веских причин использовать абстрактный признак в признаке. К сожалению, IntelliJ IDEA не различает их и просто предупреждает об их использовании повсеместно. На практике это означает, что предупреждения IntelliJ IDEA игнорируются.