Locked History Actions

Diff for "scala/callLike"

Differences between revisions 2 and 3
Deletions are marked like this. Additions are marked like this.
Line 70: Line 70:

== update ==

updateは配列への代入時

メソッド呼び出しのように見えるもの

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