implicit conversion(暗黙の型変換)


Scalaにはimplicit conversionとimpolicit Parameterという機能があります。
implicit conversionとは暗黙の型変換機能をユーザが定義できるようにする機能です。
implicit conversionは

implicit def メソッド名(引数名: 引数の型): 戻り値の方 = 本体

という形で定義します。implicitというキーワードが付いていることと引数が1つしかないことを除けば通常のメソッド定義と同様です。
implicit conversionの戻り値の型には重要な意味があります。それは、これが、引数の型の式が現れたときに戻り値の型を暗黙の変換候補として登録することになるからです。
定義したimplicit conversionは大きく分けて2通りの使われ方をします。1つは、新しく定義したユーザ定義の型などを既存の型にあてはめたい場合です。

例えば

implicit def intToBoolean(arg: Int): Boolean = arg != 0
if(1) println("1 is true")

といった形で、本来Boolean型しか渡せないはずのif式にIntを渡すことができています。しかし、これは余り良い使い方ではありません。
予期せぬエラーが発生する原因になります。

もう一つの使い方は、pimp my libraryパターンと呼ばれ、既存のクラスにメソッドを追加して拡張するようにみせかける使い方です。こちらが本来の使い方と言って良いでしょう。
試しに、Stringの末尾に":-)"を追加して返すimplicit conversionを定義してみます。

class RichString(val src: String) {
  def smile: String = src + ":-)"
}
implicit def enrichString(arg: String):RichString = new RichString(arg)
println("Hi".smile)

ちゃんと文字列の末尾に追加されています。上に書いたコードは少し冗長です。 しかし、Scala 2.10からはclassにimplicitキーワードを付けることで同じようなことをできるようになりました。 先程のコードはScala 2.10以降では以下のように書き直すことができます。

implicit class RichString(val src: String) {
  def smile: String = src + ":-)"
}
println("Hi,".smile)

基本的にScala 2.10以降でpimp my libraryパターンを使用する場合は後者の形にすべきです。