Что такое "ранний инициализатор" в Scala?

В недавнем посте Мартина Одерского об уровнях возможностей программиста в Scala в разделе конструктора библиотеки Expert он включает термин "ранние инициализаторы".

Они не упомянуты в Программирование в Scala. Кто они такие?

3 ответа

Решение

Ранние инициализаторы являются частью конструктора подкласса, который предназначен для запуска перед его суперклассом. Например:

abstract class X {
    val name: String
    val size = name.size
}

class Y extends {
    val name = "class Y"
} with X

Если код был написан вместо

class Z extends X {
    val name = "class Z"
}

тогда исключение нулевого указателя произойдет, когда Z получил инициализацию, потому что size инициализируется раньше name в обычном порядке инициализации (суперкласс перед классом).

На второй мысли, год слой...

Это всего лишь торт. В прямом смысле.

Не рано НИЧЕГО. Просто торт (миксин).

Торт - это термин / паттерн, придуманный самим Гранд-Пухом, который использует систему черт Scala, которая находится на полпути между классом и интерфейсом. Это намного лучше, чем шаблон оформления Java.

Так называемый "интерфейс" является просто безымянным базовым классом, и то, что раньше было базовым классом, действует как черта (чего я, честно говоря, не знал, можно было бы сделать). Мне неясно, может ли класс with'd принимать аргументы (черты не могут), попробует и отчитается.

Этот вопрос и его ответ вошли в одну из самых крутых особенностей Scala. Читайте об этом и будьте в восторге.

Насколько я могу судить, мотивация (как указано в ссылке выше):

"Естественно, когда val переопределяется, он не инициализируется более одного раза. Поэтому, хотя x2 в приведенном выше примере, по-видимому, определяется в каждой точке, это не тот случай: переопределенный val при создании суперклассов будет иметь значение null. как будет абстрактный вал. "

I don't see why this is natural at all. It is completely possible that the rhs of an assignment might have a side effect. Note that such code structure is completely impossible in either C++ or Java (and I will guess Smalltalk, although I can't speak for that language). In fact you have to make such dual assignments implicit...ticilpmi...EXplicit in those languages via constructors. In the light of the rhs side effect uncertainty, it really doesn't seem like much of a motivation at all: the ability to sidestep superclass side effects (thereby voiding superclass invariants) via ASSIGNMENT? Ик!

Are there other "killer" motivations for allowing such unsafe code structure? Object-oriented languages have done without such a mechanism for about 40 years (30-odd years, if you count from the creation of the language), why include it now?

It...just...seems...dangerous.

Другие вопросы по тегам