2015-10-20 12 views
5

私はScalaコンストラクタによって非常に混乱しています。たとえば、ツリー上のAddやリーフノードなどの演算子を持つツリーを表す次のクラスがあります。スカラコンストラクタ混乱 - 明確にしてください

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) 
    } 
} 

私は(val)でどのようなScalaのコンストラクタに行くすると、自動的に不変であることを一つのサイトで読んでますが、スタックオーバーフロー上のこの男は"The input parameters for the constructor are not vals unless you say they are."は、だから、1つの矛盾だと述べました。

また、私は明らかに何らかの理由でコンストラクタに "val"と "override"を追加する必要はないかもしれませんか?つまり、すべてを公開して不変にし、Addに "+"と等しいシンボル、加算関数に等しいbinaryOp、さらに2つの数値aとbを持たせたいと思う。誰かが、冗長ではない方法でコンストラクタを期待通りに動作させる方法を説明してください。

私はこのような何かを行うことができるようにしたい:

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

REPLは、クラスパラメータvalを呼び出します。 'クラスC(x:Int){def mod(y:Int):Unit = x = y}'はエラーを返します:valへの再割り当て。 – jwvh

答えて

6

あなたはほとんどあり:Scalaのクラスのコンストラクタへのすべての引数は、方法がない限り、クラスの建設後に捨てられますクラスはそれを使用します。この場合はprivate[this] valとなります。

しかし、単にあなたのコンストラクタのパラメータの前にval/varキーワードを追加することができ、それが公共val/varを作らされます。

abstract class Node(val symbol: String) {} 

通常、これは、サブクラスのコンストラクタで繰り返されていませんフィールドがすでにスーパークラスで定義されている場合:

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) { 
} 

は今、あなたはクラスの外からフィールドにアクセスすることができます

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

また、別の混乱の原因になる可能性があるので、ケースクラスは多少異なっている(パラメータはデフォルトではpublic 'vals'sです)。 –

関連する問題