|
| 1 | +--- |
| 2 | +layout: tutorial |
| 3 | +title: Type Inference |
| 4 | + |
| 5 | +disqus: true |
| 6 | + |
| 7 | +tutorial: scala-tour |
| 8 | +categories: tour |
| 9 | +num: 29 |
| 10 | +next-page: operators |
| 11 | +previous-page: polymorphic-methods |
| 12 | +prerequisite-knowledge: unified-types, generic-classes |
| 13 | +--- |
| 14 | +The Scala compiler can often infer the type of a value so you don't have to declare it explicitly. You'll often see this with variables and return types. |
| 15 | + |
| 16 | +## Omitting the type |
| 17 | +``` |
| 18 | +val businessName = "Montreux Jazz Café" |
| 19 | +``` |
| 20 | +The compiler can detect that `businessName` is a String. It works similarly with methods: |
| 21 | +``` |
| 22 | +def squareOf(x: Int) = x * x |
| 23 | +``` |
| 24 | +The compiler can infer that the return type is an int so no return type is required. |
| 25 | + |
| 26 | +For recursive methods, the compiler is not able to infer a result type. Here is a program which will fail the compiler for this reason: |
| 27 | + |
| 28 | +```tut:fail |
| 29 | +def fac(n: Int) = if (n == 0) 1 else n * fac(n - 1) |
| 30 | +``` |
| 31 | + |
| 32 | +It is also not compulsory to specify type parameters when [polymorphic methods](polymorphic-methods.html) are called or [generic classes](generic-classes.html) are instantiated. The Scala compiler will infer such missing type parameters from the context and from the types of the actual method/constructor parameters. |
| 33 | + |
| 34 | +Here are two examples: |
| 35 | +``` |
| 36 | +case class MyPair[A, B](x: A, y: B); |
| 37 | +val p = MyPair(1, "scala") // type: MyPair[Int, String] |
| 38 | +
|
| 39 | +def id[T](x: T) = x |
| 40 | +val q = id(1) // type: Int |
| 41 | +``` |
| 42 | +The compiler uses the types of the arguments of `MyPair` to figure out what type `A` and `B` are. Likewise for the type of `x`. |
| 43 | + |
| 44 | +## Parameters |
| 45 | +The compiler can never infer method parameter types. However, in certain cases, it can infer anonymous function parameter types when the function is passed as argument. |
| 46 | + |
| 47 | +``` |
| 48 | +val doubled = Seq(1, 3, 4).map(x => x * 2) // List(2, 6, 8) |
| 49 | +``` |
| 50 | +The parameter for map is `f: A => B`. Because we put integers in the Seq, the compiler knows that `A` is `Int` (i.e. that `x` is an int). Therefore, the compiler can infer from `x * 2` that `B` is type `Int`. |
| 51 | + |
| 52 | +## When _not_ to rely on type inference |
| 53 | + |
| 54 | +It is generally considered more readable to declare the type of members exposed in a public API. Also, in some situations it can be quite dangerous to rely on Scala's type inference mechanism as the following program shows: |
| 55 | + |
| 56 | +```tut:fail |
| 57 | +object InferenceTest4 { |
| 58 | + var obj = null |
| 59 | + obj = new Object() |
| 60 | +} |
| 61 | +``` |
| 62 | + |
| 63 | +This program does not compile because the type inferred for variable `obj` is `Null`. Since the only value of that type is `null`, it is impossible to make this variable refer to another value. |
0 commit comments