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