Implicit Conversion とは、暗黙の型変換をユーザが定義できるようにする機能、だそうだ。例えば、真偽値が必要なところにユーザ定義型が来たとき、その型を真偽値に変換する Implicit Conversion が定義されていれば、エラーにならずに変換される、ってことらしい。
Implicit Conversion の定義は implicit キーワードをつけたメソッド定義だと思えばいい。あとは引数が1つであることくらいか。Int を Boolean に変換する Implicit Conversion の定義はこんな感じ。
scala> implicit def intToBoolean(arg: Int): Boolean = arg != 0
warning: there was one feature warning; for details, enable :setting -feature' or
:replay -feature'
intToBoolean: (arg: Int)Boolean
メソッド名はたぶん何でもいい。重要なのは引数の型と返り値の型。次の例のように、Boolean でなければいけないところ(if の条件式)に Int が来たとき、Scala は Implicit Conversion を探して、あてはまるものが見つかったらそれを適用してくれる。その結果、次のようになる。
scala> if (1) { | println("1 is true.") | } 1 is true.
本来、if の条件式は Boolean でなければならないけど、暗黙の型変換が働いて Int を Boolean に変換した結果、1 is true. と出力されている。
もっとも、この使い方はあまり好ましくないようだ。
もうひとつの使い方は、pimp my library パターンとよばれ、既存のクラスにメソッドを追加して拡張するように見せかける使い方だ。例として、文字列の最後にスマイルマーク :-) をくっつけて返す Implicit Conversion を考えよう。
scala> class RichString(val src: String) {
| def smile: String = src + ":-)"
| }
defined class RichString
scala> implicit def enrichString(arg: String): RichString = new RichString(arg)
warning: there was one feature warning; for details, enable :setting -feature' or
:replay -feature'
enrichString: (arg: String)RichString
enrichString が Implicit Conversion だ。String を RichString に変換する。次のように使う。
scala> "Hi, ".smile res2: String = Hi, :-)
“Hi, ” は String なので smile なんていうメソッドは持っていない。だけど Implicit Conversion のおかげで暗黙に RichString に変換されて、smile メソッドが呼ばれている。
さて、上の例は Scala 2.10 以降では Implicit Class という機能で実現できる。
scala> implicit class RichString(val src: String) { | def smile: String = src + ":-)" | } defined class RichString scala> "Hi, ".smile res0: String = Hi, :-)
Implicit Class は pimp my library 専用の機能なので、通常はこっちを使うといいようだ。