2015-10-20 14 views
5

Sono molto confuso da Scala Constructors. Ad esempio, ho le seguenti classi che rappresentano un albero con operatori come Aggiungi e nodi foglia sull'albero che sono numeri.Confusione costruttore di scala - chiarire

abstract class Node(symbol: String) {} 

abstract class Operator(symbol: String, 
     binaryOp: (Double, Double) => Double) extends Node(symbol) { 
} 

class Add(a: Number, b: Number) extends 
     Operator("+", (a: Double, b: Double) => a+b) { 
} 

class Number(symbol: String) extends Node(symbol) { 
    val value = symbol.toDouble 
    def this(num: Double) { 
     this(num.toString) 
    } 
} 

ho letto in un sito che ciò che accade in un costruttore Scala è automaticamente immutabili (val), ma questo ragazzo su Stack Overflow detto "The input parameters for the constructor are not vals unless you say they are." Quindi questa è una contraddizione.

Inoltre, a quanto pare, potrebbe non essere necessario aggiungere "val" e "override" nei costruttori per qualche motivo? Voglio dire che voglio che tutto sia pubblico e immutabile e che Aggiungi abbia un simbolo uguale a "+", un binarioOp uguale alla funzione di addizione e anche due numeri a e b. Qualcuno può spiegare come far funzionare i costruttori come previsto in Scala in modo non verboso?

Voglio essere in grado di fare qualcosa del genere:

addition = Add(Number(1), Number(2)) 
addition.binaryOp(addition.a.value, addition.b.value) 
+0

Il REPL chiama i parametri di classe vals. 'classe C (x: Int) {def mod (y: Int): Unit = x = y}' produce 'errore: riassegnazione a val'. – jwvh

risposta

6

siete quasi arrivati: Ogni argomento al costruttore di una classe Scala viene gettato via dopo la costruzione della classe, a meno che un metodo della la classe lo usa. In questo caso, viene creato come private[this] val.

Tuttavia, si può semplicemente aggiungere la parola val/var davanti al parametro del costruttore e sarà fatto un pubblico val/var:

abstract class Node(val symbol: String) {} 

Di solito, questo non si ripeta nel costruttore per le sottoclassi se il campo è già definito nella superclasse:

abstract class Operator(symbol: String, // no val here, only pass to super class 
     val binaryOp: (Double, Double) => Double) extends Node(symbol) { 
} 

class Add(val a: Number, val b: Number) extends 
    Operator("+", (a: Double, b: Double) => a+b) { 
} 

Ora è possibile accedere ai campi da fuori classe:

addition = Add(Number(1), Number(2)) 
addition.binaryOp(addition.a.value, addition.b.value) 
+4

Potrebbe anche valere la pena ricordare che le classi dei casi sono in qualche modo differenti (i parametri sono di default 'vals's per impostazione predefinita), poiché ciò potrebbe essere un'altra fonte di confusione. –