Предположим, вы изменили определение delayInit
на запретное, т. Е.
def delayedInit(x: => Unit) { }
Затем в вашем основном методе сделайте что-то вроде
println("FP.imp: " + FalsePositive.imp)
Как и ожидалось,напечатайте FP.imp: null
, но реальная цель упражнения - проиллюстрировать, что блок, который определяет тело FalsePositive
, действует как тело обычного класса, а не как тело функции.Он определяет открытые члены, когда видит val
, а не локальные переменные.
Если вы добавили метод к AnnoyingObjectForNoPurpose
, как показано ниже, он не скомпилируется, потому что неявное требование print
не являетсяудовлетворен.
def fails {
print(321)
implicit val cantSeeIt = new Printer[Int] {
def doPrint(v: Int) = println(v + " doesn't compile")
}
}
Однако, если вы определили класс по тому же принципу, он скомпилируется, но завершится неудачно при инициализации, как ваш пример FalsePositive
.
class Fine {
print(321)
implicit val willBeNull = new Printer[Int] {
def doPrint(v: Int) = println(v + " compiles, but fails")
}
}
Чтобы было ясно, поведение компиляции Fine
не имеет ничего общего с присутствием implicit
.Инициализаторы класса / объекта очень рады компилировать с val
инициализаторами, которые ссылаются на undefined val
s.
object Boring {
val b = a
val a = 1
println("a=%s b=%s".format(a, b))
}
Boring
компилируется очень хорошо, и когда на него ссылаются, он печатает a=1 b=0
Похоже, ваш вопрос сводится к "Должно ли тело класса / объекта, происходящего из DelayedInit
, быть скомпилировано так, как если бы оно было телом класса или функциональным блоком?"
Похоже на Одерскоговыбрал первое, но вы надеетесь на второе.