Fight the Future

Java言語とJVM、そしてJavaエコシステム全般にまつわること

ScalaのSnippetを写経する(5)-Implicit Conversion

Snippet: Extend Builtins | The Scala Programming Language

Scalaの特徴的な機能であるImplicit Conversion(暗黙的な型変換)。
Implicit ConversionについてはJJUG CCCのBOFでもScalaについて話されていた水島さんの資料がわかりやすいです。
http://www.coins.tsukuba.ac.jp/~i021216/docs/Scala-implicit-conversion.pdf

package sample.snippet

object ExtendBuiltins extends Application {
  
  def fact(n: Int): BigInt = {
    if(n == 0) {
      1
    } else {
      fact(n -1) * n
    }
  }
  
  class Factorizer(n: Int) {
    def ! = fact(n)
  }
  
  implicit def int2fact(n: Int) = new Factorizer(n)
  
  println(new Factorizer(5).!)
  println(new Factorizer(5) !)
  println(10 !)
  // below code is compile error. why??
  // println(10.!) 
  println(10!)
  
}

詳細は後で解説するとして、注目は「10!」。
10はもちろんInt型だし、「!」なんてメソッドは定義されていない。
だけどこのコードはコンパイルエラーにも実行時エラーにもならない。


Implicit Conversionを利用しているから。


implicitというキーワードを使ってメソッドを定義してる。それがint2fact。
この引数と戻り値がポイント。引数はIntで戻り値はFactorizer。
つまり、Intにないメソッド呼び出しもこのImplicitにした変換メソッドを検知してFactorizer型に変換し、
Factorizerの「!」を呼び出しているってこと。
変換するたびにインスタンスを生成って勉強会で聞いたような気がする。


だからまるでInt型に階乗を計算するメソッド「!」を定義したかのように使えちゃう。

わからないこと

メソッド呼び出しなんで

  • println(10!)
  • println(10 !)
  • println(10.!)

のどれもいけると思ったけど、println(10.!)はコンパイルエラーになってしまう。。。
なんでだろう??理解を誤っているのかな。。。