メソッドとフィールド
パラメーターなしメソッドと空括弧メソッド
Scalaにはパラメーターなしメソッドと空括弧メソッドがある。
言葉を聞いてもどっちがどっちだか分からないくらいややこしい。
パラメーターなしメソッドは、メソッドの定義の際に、仮引数がないうえにそれを囲む括弧も記述しない。
空括弧メソッドは、仮引数はないが空の括弧は記述する。
以上は定義の際の話。
パラメーターなしメソッドは、空括弧つきで呼び出すことはできない。
空括弧メソッドは、空括弧つきでもなしでも呼び出せる。
実にややこしい。
どの組み合わせが許されるのか、実験しないと分からないじゃないか。
(01) def met01 = println("OK") // met01: Unit
(02) def met02() = println("OK") // met02: Unit
(03) met01 // OK
(04) met02 // OK
(05) met01() // error: met01 of type Unit does not take parameters
(06) met02() // OK
ふーん。
もう一例。まずメソッド定義。
(07) def met03 = {println("OK");5} // met03: Int
(08) def met04() = {println("OK");5} // met04: ()Int
(09) def met05 = ()=>{println("OK");5} // met05: () => Int
実行。
(09) var m = met03() // error: met03 of type Int does not take parameters
(10) var m = met04() // OK m: Int = 5
(11) var m = met05() // OK m: Int = 5
(12) var m = met03 // OK m: Int = 5
(13) var m = met04 // OK m: Int = 5
(14) var m = met05 //m: () => Int =
この例ではmet04とmet05が空括弧付きで実行すると同じ結果になる。
つまり実行して5をmに代入する。
が、括弧を省略すると結果が異なる。
met05の場合、関数オブジェクトがmに代入されるのである。
つまりメソッドの定義方法によっては、空の括弧を付けるか付けないかで意味が異なってくる。
使用者は、内部の実装を見ないとどう解釈されるか分からないことになる。
こんな仕様でいいのか?
実行時の括弧は省略不可にすべきだと思う。
defとval・var
メソッドの定義や呼び出しで括弧をつけないとなると、見掛け上、defはvalやvarとまったく同じ記述になる。
さらに、valやvarには関数値を代入できるので、逆にdefの定義と同じようなこともできてしまう。
結局、Scalaのdefとvalの違いは何だ?
Scalaは最終的にJavaのバイトコードになるので、Javaの言葉でいうと、defはJavaのメソッド、valやvarはJavaのフィールドになる。
とんでもなく当たり前の話だ。
Javaではメソッドはインスタンスには表れないので、格納する場所が違うということは予想できる。
defはクラス領域に、valやvarはインスタンスにできると思われる。
が、それはあくまで実装上の話で、言語仕様とはあまり関係がない。
Javaではメソッドとフィールドはまったく別物であり、目的も異なるが、Scalaではほとんど同じように使えるので、違いが分かり難い。
実装に関することを除けば、変更不可能なものを代入している場合、defとvalはほとんど区別できないと思う。
(01) def d1 = 5 // d1: Int
(02) val v1 = 5 // v1: Int = 5
上のように露骨な例でなくても、例えば関数リテラルを代入する例などでも同じだろう。
(03) def d1 = (x:Int, y:Int)=>x + y // d1: (Int, Int) => Int
(04) val v2 = (x:Int, y:Int)=>x + y // v1: (Int, Int) => Int = <function>
違いが出るのは、次のように変更可能なものを代入している場合のようだ
(05) var a = 1
(06) def d3 = a // d3: Int
(07) val v3 = a // v3: Int = 1
(08) a = 2
(09) println(d3) // 2
(10) println(v3) // 1
上の場合(07)のvalはvarに変えた方がdefと同じ結果になる可能性が生まれるかもしれないが、当然結果は変わらない。