2011-01-17 12 views

risposta

91

I primi inizializzatori fanno parte del costruttore di una sottoclasse destinata all'esecuzione prima della sua superclasse. Ad esempio:

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

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

Se il codice è stato scritto invece come

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

quindi un'eccezione di puntatore nullo si verificherebbe quando Z preso inizializzato, perché size viene inizializzato prima name nel normale ordine di inizializzazione (superclasse prima della lezione).

+0

In che modo è preferibile al nome errato 'def nameInit: String; val name = nameInit', sovrascritto da 'def nameInit =" foo "'? – nadavwr

+1

@nadavwr Un 'def' sarà sovrascritto dalla tabella dei metodi della classe, garantendo così la versione più specifica verrà eseguita, mentre non c'è nulla di simile all'inizializzazione di' val' - ciò che viene sovrascritto è il getter, non l'initalization . –

2

Per quanto posso dire, la motivazione (come indicato nel link qui sotto) è:

"Naturalmente quando una val viene ignorata, non è inizializzato più di una volta Quindi, anche se x2 nell'esempio di cui sopra. è apparentemente definito in ogni punto, questo non è il caso: una val di override apparirà nullo durante la costruzione di superclassi, così come una val astratta. "

Non vedo perché questo è naturale. È completamente possibile che il r.h.s. di un incarico potrebbe avere un effetto collaterale. Si noti che tale struttura di codice è completamente impossibile in C++ o Java (e suppongo che Smalltalk, sebbene non possa parlare per quella lingua). In realtà devi fare questi doppi incarichi impliciti ... ticilpmi ... EXPlicit in quei linguaggi tramite costruttori. Alla luce del r.h.s. incertezza dell'effetto collaterale, in realtà non sembra affatto una motivazione: la capacità di aggirare gli effetti collaterali della superclasse (annullando in tal modo gli invarianti della superclasse) tramite ASSIGNMENT? Ick!

Esistono altre motivazioni "killer" per consentire una struttura del codice non sicura? I linguaggi orientati agli oggetti hanno fatto a meno di un tale meccanismo per circa 40 anni (30 anni dispari, se contate dalla creazione della lingua), perché includerlo ora?

E ... solo ... sembra ... pericoloso.

+0

Anche questo non ha senso per me, e direi che una volta che ho iniziato a scavalcare vals, sono già in territorio pericoloso. Sostituire una def che viene assegnata a una val ha molto più senso per me. Suggerimenti di stile per i calci: "implicito ... ticilpmi ... EXplicit" -> "impli [^ H^H^H^H^H] (http://en.wikipedia.org/wiki/Backspace#.5EH EXPlicit " – nadavwr

+0

Qualcuno ha ovviamente mai usato un terminale cartaceo ... sì, ragazzi ... ne avevano una volta :-) –

1

Il secondo pensiero, uno strato anno ...

questo è solo torta. Letteralmente.

Non un primo ANYTHING. Basta torta (mixin).

Cake è un termine/pattern coniato da The Grand Pooh-bah stesso, uno che utilizza il sistema dei tratti di Scala, che è a metà strada tra una classe e un'interfaccia. È molto meglio del modello di decorazione di Java.

La cosiddetta "interfaccia" è semplicemente una classe base senza nome, e quella che era la classe base sta agendo come un tratto (che francamente non sapevo si potesse fare). Non è chiaro per me se una classe "with'd" possa accettare argomenti (i tratti non possono), la proverà e farà rapporto.

Questa domanda e la sua risposta sono entrati in uno degli aspetti più interessanti di Scala. Leggi su di esso ed essere in soggezione.

+0

Da EBNF di Scala:' ClassTemplate :: = [EarlyDefs] ClassParents [TemplateBody] ', 'ClassParents :: = Constr {'con' AnnotType}' e 'Constr :: = AnnotType {'(' [Esprs] ')'}', direi che la classe "with'd" può accettare argomenti. – themarketka

Problemi correlati