メソッド呼び出しのように見えるもの
Scalaの(特殊な?)文法
Scalaにはオブジェクトに対する直接のメソッド呼び出しのように見える構文がある。 これはJavaで言えばnewの無いコンストラクタ呼び出しのようである。
同じような書き方をしても文脈によって動作は異なり、その動作は実際にはupdate,apply,unapplyというメソッドによって定義される。 例えば以下のようなコードを考えてみる。
class CallLike { def update(i: Int, j:Int, value: String): Unit = { println("update") } def apply(i: Int, j: Int): Unit = { println("apply") } def unapply(value: String) = { println("unapply"); Some(30, 40) } } object Main { def main(args: Array[String]) { val obj = new CallLike(); obj(1, 2) = "abc"// update obj(3, 4) // apply val obj(x, y) = "xyz"; // unapply } }
この実行結果は
update apply unapply
になる。同じ一つのobjに続けてカッコをつけて引数(及び引数のようなもの)を記述したとしても、文脈によって実際に呼び出されるメソッドが異なる。
- updateは、右側に代入演算子(?)のついている場合
- applyは、代入されていない(ように見える)場合
- unapplyは、変数定義と同時に初期化している(ように見える)場合
もう少し動作確認
本当に期待する通りの動作を行っているのか、確認のために次のように記述してみる。
class CallLike { def update(i: Int, j:Int, value: String) = { println("update %d %d %s" format (i, j, value)); 10 } def apply(i: Int, j: Int) = { println("apply %d %d" format (i, j)); 20 } def unapply(value: String) = { println("unapply %s" format value); Some(30, 40) } } object Main { def main(args: Array[String]) { val obj = new CallLike(); val updateReturn = obj(1, 2) = "abc"; // update println("updateReturn %d" format updateReturn); val applyReturn = obj(3, 4) // apply println("applyReturn %d" format applyReturn); val obj(x, y) = "xyz"; // unapply println("unapplyReturn %d %d" format (x, y)) } }
この結果は以下。
update 1 2 abc updateReturn 10 apply 3 4 applyReturn 20 unapply xyz unapplyReturn 30 40