Определение значений экземпляра Scala

Note that this question and similar ones have been asked before, such as in Прямые ссылки - почему этот код компилируется?, но я нашел ответы, чтобы все еще оставить некоторые вопросы открытыми, поэтому у меня есть другой подход к этому вопросу.

В рамках методов и функций, эффект отval Ключевое слово выглядит как лексическое, т.е.

<code>def foo {
  println(bar)
  val bar = 42
}
</code>

получая

<code>error: forward reference extends over definition of value bar
</code>

Тем не менее, в классах, обзорные правилаval кажется, измениться:

<code>object Foo {
  def foo = bar
  println(bar)
  val bar = 42
}
</code>

Это не только компиляция, но иprintln в конструкторе будет давать0 как его вывод, при вызовеfoo после того, как экземпляр полностью построен, получится ожидаемое значение42.

Таким образом, представляется возможным для методов пересылать ссылки на значения экземпляров, которые, в конечном итоге, будут инициализированы до вызова метода (если, конечно, вы не вызываете его из конструктора), а также для операторов внутри конструктора направлять ссылочные значения таким же образом, получая доступ к ним до их инициализации, что приводит к глупому произвольному значению.

Отсюда возникает пара вопросов:

Why does val use its lexical compile-time effect within constructors?

Учитывая, что конструктор - это на самом деле всего лишь метод, это кажется довольно непоследовательным, чтобы полностью отброситьval'Эффект времени компиляции, придающий ему только обычный эффект времени выполнения.

Why does val, effectively, lose its effect of declaring an immutable value?

Доступ к значению в разное время может привести к разным результатам. Для меня это очень похоже на утечку деталей реализации компилятора.

What might legitimate usecases for this look like?

Мне трудно придумать пример, который абсолютно требует текущей семантикиval внутри конструкторов и не могут быть легко реализованы с помощью правильной, лексическойvalвозможно в сочетании сlazy.

How would one work around this behaviour of val, getting back all the guarantees one is used to from using it within other methods?

Можно, по-видимому, объявить все инстанцииvalс бытьlazy чтобы вернуться кval быть неизменным и давать один и тот же результат, независимо от того, как к ним осуществляется доступ, и сделать эффект времени компиляции, наблюдаемый в обычных методах, менее актуальным, но это кажется мне ужасным хаком для такого рода вещей.

Учитывая, что это поведение вряд ли когда-либо изменится в реальном языке, будет ли плагин компилятора подходящим местом для решения этой проблемы, или возможно ли реализоватьval-подобное ключевое слово с, для кого-то, кто только что потратил час на отладку проблемы, вызванной этой странностью, более разумной семантики в языке?

Ответы на вопрос(2)

Ваш ответ на вопрос