71

In Martin Odersky's recent post about levels of programmer ability in Scala, in the Expert library designer section, he includes the term "early initializers".

These are not mentioned in Programming in Scala. What are they?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
oxbow_lakes
  • 133,303
  • 56
  • 317
  • 449

3 Answers3

108

Early initializers are part of the constructor of a subclass that is intended to run before its superclass. For example:

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

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

If the code was written instead as

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

then a null pointer exception would occur when Z got initialized, because size is initialized before name in the normal ordering of initialization (superclass before class).

0__
  • 66,707
  • 21
  • 171
  • 266
Daniel C. Sobral
  • 295,120
  • 86
  • 501
  • 681
  • In what way is this preferable to the awkwardly named `def nameInit: String; val name = nameInit`, overridden by `def nameInit = "foo"`? – nadavwr May 04 '13 at 18:12
  • 2
    @nadavwr A `def` will be overridden by the method table of the class, thus guaranteeing the most specific version will be executed, whereas there's no such thing for `val` initializations -- what gets overridden is the getter, not the initalization. – Daniel C. Sobral May 07 '13 at 22:37
2

As far as I can tell, the motivation (as given in the link above) is:

"Naturally when a val is overridden, it is not initialized more than once. So though x2 in the above example is seemingly defined at every point, this is not the case: an overridden val will appear to be null during the construction of superclasses, as will an abstract val."

I don't see why this is natural at all. It is completely possible that the r.h.s. 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 r.h.s. 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? Ick!

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.

Mark Gerolimatos
  • 2,424
  • 1
  • 23
  • 33
  • This doesn't make complete sense to me as well, and I would argue that once I've started overriding vals I'm already in dangerous territory. Overriding a def that gets assigned to a val makes much more sense to me. Style suggestion for kicks: "implicit...ticilpmi...EXplicit" --> "impli[^H^H^H^H^H](http://en.wikipedia.org/wiki/Backspace#.5EH)EXplicit" – nadavwr May 04 '13 at 18:07
  • Someone has obviously never used a paper-based terminal...yes, kids...they had those once :-) – Mark Gerolimatos Nov 20 '13 at 17:22
2

On second thought, a year layer...

This is just cake. Literally.

Not an early ANYTHING. Just cake (mixins).

Cake is a term/pattern coined by The Grand Pooh-bah himself, one that employs Scala's trait system, which is halfway between a class and an interface. It is far better than Java's decoration pattern.

The so-called "interface" is merely an unnamed base class, and what used to be the base class is acting as a trait (which I frankly did not know could be done). It is unclear to me if a "with'd" class can take arguments (traits can't), will try it and report back.

This question and its answer has stepped into one of Scala's coolest features. Read up on it and be in awe.

Mark Gerolimatos
  • 2,424
  • 1
  • 23
  • 33
  • From EBNF of Scala: `ClassTemplate ::= [EarlyDefs] ClassParents [TemplateBody]`, `ClassParents ::= Constr {'with' AnnotType}` and `Constr ::= AnnotType {'(' [Exprs] ')'}`, I’d say that "with’d" class can take arguments. – themarketka Jul 25 '14 at 11:28