Scala ひと巡り : ローカルな型推論 (Local Type Inference)

原ページ

Scala は、プログラマが明白なアノテーション型を書かなくても済む、組み込みの型推論機構を持っています。たとえば Scalaでは、変数の型を指定する必要がないことがよくあります。なぜなら、コンパイラが変数の初期化式から型を推論できるからです。同様にメソッドの 戻り値型もしばしば省略できます。なぜなら、それらは本体の型に対応するので、コンパイラが推論できるからです。

次は 1 つの例です:

object InferenceTest1 extends Application { val x = 1 + 2 * 3 // x の型は Int val y = x.toString() // y の型は String def succ(x: Int) = x + 1 // メソッド succ は Int 値を返す }

再帰的なメソッドについては、コンパイラは結果型を推論できません。次のプログラムは、この理由でコンパイルできません。

object InferenceTest2 { def fac(n: Int) = if (n == 0) 1 else n * fac(n - 1) }

多相的メソッド [25]を呼ぶあるいは、ジェネリッククラス [16]をインスタンス化するとき、型パラメータの指定も必須ではありません。Scala コンパイラは、コンテキストや実際のメソッド/コンストラクタ・パラメータの型からそのような記述されていない型パラメータを推論します。

次はこのことを示す例です:

case class MyPair[A, B](x: A, y: B); object InferenceTest3 extends Application { def id[T](x: T) = x val p = new MyPair(1, "scala") // 型: MyPair[Int, String] val q = id(1) // 型: Int }

上記プログラムの最後の 2 行は、推論された型をすべて明示した、次のコードに等価です:

val x: MyPair[Int, String] = new MyPair[Int, String](1, "scala") val y: Int = id[Int](1)

ある状況では、次のプログラムが示すように、Scala の型推論機構に頼ることは非常に危険です。

object InferenceTest4 { var obj = null obj = new Object() }

このプログラムはコンパイルできません。なぜなら、変数 obj の推論される型は Null だからです。この型の唯一の値は nullですから、この変数に他の値を参照させることはできません。