2009-07-13 6 views
59

In Scala, il costruttore principale di una classe non ha un corpo esplicito, ma è definito implicitamente dal corpo della classe. In che modo, quindi, si fa una distinzione tra campi e valori locali (cioè, i valori sono locali rispetto al metodo del costruttore)?Come si definisce una var/val locale nel costruttore principale in Scala?

Per esempio, prendete il seguente frammento di codice, una forma modificata di alcuni esempi di codice da "Programmazione in Scala":

class R(n: Int, d: Int) { 
    private val g = myfunc 
    val x = n/g 
    val y = d/g 
} 

mia comprensione è che questo genererà una classe con tre campi: un privato " g "e public" x "e" y ". Tuttavia, il valore g viene utilizzato solo per il calcolo dei campi x e y e non ha alcun significato oltre l'ambito del costruttore.

Quindi, in questo esempio (certamente artificiale), come si va a definire i valori locali per questo costruttore?

+0

Pubblicare nel caso in cui altri hanno una domanda simile alla mia e sono venuti qui prima come ho fatto io. Se stai provando a fare lo stesso concetto ma per i costruttori, usa la risposta alla mia domanda: https://stackoverflow.com/questions/46455835/how-to-define-val-inside-class-constructor-in-scala –

risposta

37

E.g.

class R(n: Int, d: Int) { 
    val (x, y) = { 
    val g = myfunc 
    (n/g, d/g) 
    } 
} 
+0

Ah, davvero semplice. Sto ancora ricevendo la mia intuizione attorno al concetto funzionale. – skaffman

+47

Questo aggiungerà effettivamente un campo Tuple2 nascosto alla tua classe. –

+2

Questo può essere importante. Grazie per il commento, Jorge. –

16

Ci sono alcuni modi per farlo. È possibile dichiarare tali variabili temporanee all'interno di definizioni private, da utilizzare durante i tempi di costruzione. Puoi usare variabili temporanee all'interno di blocchi che restituiscono espressioni (come nella risposta di Alaz). O, infine, è possibile utilizzare tali variabili all'interno di costruttori alternativi.

In modo simile ai costruttori alternativi, è possibile definirli anche all'interno del metodo "apply" dell'oggetto companion.

Cosa non è do è dichiarare un campo "temporaneo".

Si noti inoltre che qualsiasi parametro ricevuto dal costruttore principale è anche un campo. Se non si desidera che tali parametri diventino campi e non si desidera esporre i campi effettivi in ​​un costruttore, la soluzione usuale è rendere privato il costruttore principale, con i campi effettivi, e utilizzare un costruttore alternativo o un object-companion's apply() come costruttore effettivo "primario".

+0

Grazie per il chiarimento. – skaffman

6

Alcune discussioni su questo argomento, tra i commenti di Martin Odersky, è here

+0

Questo è l'esatto esempio del libro che ha attivato la mia domanda :) Suppongo significhi che stavo prestando attenzione ... – skaffman

+0

La discussione è stata cancellata. – ziggystar

+5

Link alternativo: http://www.scala-lang.org/node/1198#comment-3430 – robinst

11

Un'altra opzione che abbiamo è quello di rendere il costruttore oggetto primario privato e utilizzare un compagno di oggetto metodo applicare come un costruttore. Se applichiamo (gioco di parole non è intesa) questo approccio per il vostro esempio sarà simile a questa:

class R private (val x: Int, val y: Int); 

object R { 
    def apply(n: Int, d: Int): R = { 
    val g = myfunc; 
    new R(n/g, d/g); 
    } 
} 

per creare un'istanza R, invece di:

val r = new R(1, 2); 

scrittura:

val r = R(1, 2); 

Questo è un po 'prolisso, ma potrebbe essere peggio, penso :). Speriamo che i privati ​​[this] vals saranno trattati come variabili temporanee nelle versioni future di Scala. Lo stesso Martin ha accennato.

+1

L'ottimizzazione non è ancora stata implementata a partire da Scala 2.9.0.RC1. – robinst

+0

robinst, anche in Scala 2.10.2 – MyTitle