Implicits in Scala
Scala provides implicit conversions and parameters. Implicit conversion to an expected type is the first place the compiler uses implicits. For example, the following works:
scala> val d: Double = 2 d: Double = 2.0
Example 1.65
This works because of the following implicit method definition in the Int companion object (it was part of Predef prior to 2.10.x):
implicit def int2double(x: Int): Double = x.toDouble
Example 1.66
Another application of implicit conversion is the receiver of a method call. For example, let’s define a Rational class:
scala> class Rational(n: Int, d: Int) extends Ordered[Rational] {
|
| require(d != 0)
| private val g = gcd(n.abs, d.abs)
| private def gcd(a: Int, b: Int): Int = if (b == 0) a else gcd(b, a % b)
| val numer = n / g
| val denom = d / g
| def this(n: Int) = this(n, 1)
| def +(that: Rational) = new Rational(
| this.numer * that.numer + this.denom * that.denom,
| this.denom * that.denom
| )
| def compare(that: Rational) = (this.numer * that.numer - this.denom * that.denom)
| override def toString = if (denom == 1) numer.toString else s"$numer/$denom"
| }
defined class Rational
Example 1.67
Then declare a variable of the Rational type:
scala> val r1 = new Rational(1) r1: Rational = 1 scala> 1 + r1 <console>:14: error: overloaded method value + with alternatives: (x: Double)Double <and> (x: Float)Float <and> (x: Long)Long <and> (x: Int)Int <and> (x: Char)Int <and> (x: Short)Int <and> (x: Byte)Int <and> (x: String)String cannot be applied to (Rational) 1 + r1 ^
Example 1.68
If we try to add r1 to 1, we will get a compile-time error. The reason is the + method in Int does not support an argument of type Rational. In order to make it work, we can create an implicit conversion from Int to Rational:
scala> implicit def intToRational(n: Int): Rational = new Rational(n) intToRational: (n: Int)Rational scala> val r1 = new Rational(1) r1: Rational = 1 scala> 1 + r1 res11: Rational = 2
Example 1.69