Implicit conversions in Scala

An implicit conversion from type S to type T is defined by an implicit value that has function type S => T, or by an implicit method convertible to a value of that type. Implicit conversions are applied in two situations (source: http://docs.scala-lang.org/tutorials/tour/implicit-conversions):

  • If an expression e is of type S, and S does not conform to the expression's expected type T
  • In a selection e.m with e of type S, if the selector m does not denote a member of S.

Well, we have seen how to use infix operator in Scala. Now, let's see some use cases of Scala implicit conversion. Suppose we have the following code segment:

class Complex(val real: Double, val imaginary: Double) {
def plus(that: Complex) = new Complex(this.real + that.real, this.imaginary + that.imaginary)
def minus(that: Complex) = new Complex(this.real - that.real, this.imaginary - that.imaginary)
def unary(): Double = {
val value = Math.sqrt(real * real + imaginary * imaginary)
value
}
override def toString = real + " + " + imaginary + "i"
}
object UsingImplicitConversion {
def main(args: Array[String]): Unit = {
val obj = new Complex(5.0, 6.0)
val x = new Complex(4.0, 3.0)
val y = new Complex(8.0, -7.0)

println(x) // prints 4.0 + 3.0i
println(x plus y) // prints 12.0 + -4.0i
println(x minus y) // -4.0 + 10.0i
println(obj.unary) // prints 7.810249675906654
}
}

In the preceding code, we defined some methods for performing addition, subtraction, and a unary operation for complex numbers (that is, both real and imaginary numbers). Inside the main() method, we called these methods with real values. The output is given as follows:

4.0 + 3.0i
12.0 + -4.0i
-4.0 + 10.0i
7.810249675906654


But what if we want to support adding a normal number to a complex number, how would we do that? We could certainly overload our plus method to take a Double argument so that it's going to support the following expression.

val sum = myComplexNumber plus 6.5

For this, we can use Scala implicit conversion. It supports implicit conversion for both real and complex numbers for mathematical operation. So, we can just use that tuple as the parameter for our implicit conversion and convert it into a Complex refer to the following:

implicit def Tuple2Complex(value: Tuple2[Double, Double]) = new Complex(value._1, value._2)

Alternatively, for double to complex conversion as follows:

implicit def Double2Complex(value : Double) = new Complex(value,0.0) 

To take the advantage of this conversion, we need to import the following:

import ComplexImplicits._ // for complex numbers
import scala.language.implicitConversions // in general

Now, we can execute something like this on Scala REPL/IDE:

val z = 4 plus y
println(z) // prints 12.0 + -7.0i
val p = (1.0, 1.0) plus z
println(p) // prints 13.0 + -6.0i

You will get the following output:

12.0 + -7.0i
13.0 + -6.0i

The full source code for this example can be seen as follows:

package com.chapter4.CollectionAPI
import ComplexImplicits._
import scala.language.implicitConversions
class Complex(val real: Double, val imaginary: Double) {
def plus(that: Complex) = new Complex(this.real + that.real, this.imaginary + that.imaginary)
def plus(n: Double) = new Complex(this.real + n, this.imaginary)
def minus(that: Complex) = new Complex(this.real - that.real, this.imaginary - that.imaginary)
def unary(): Double = {
val value = Math.sqrt(real * real + imaginary * imaginary)
value
}
override def toString = real + " + " + imaginary + "i"
}
object ComplexImplicits {
implicit def Double2Complex(value: Double) = new Complex(value, 0.0)
implicit def Tuple2Complex(value: Tuple2[Double, Double]) = new Complex(value._1, value._2)
}
object UsingImplicitConversion {
def main(args: Array[String]): Unit = {
val obj = new Complex(5.0, 6.0)
val x = new Complex(4.0, 3.0)
val y = new Complex(8.0, -7.0)
println(x) // prints 4.0 + 3.0i
println(x plus y) // prints 12.0 + -4.0i
println(x minus y) // -4.0 + 10.0i
println(obj.unary) // prints 7.810249675906654
val z = 4 plus y
println(z) // prints 12.0 + -7.0i
val p = (1.0, 1.0) plus z
println(p) // prints 13.0 + -6.0i
}
}

We have now more or less covered Scala collection APIs. There are other features too, but page limitations prevented us from covering them. Interested readers who still want to explore this should refer to this page http://www.scala-lang.org/docu/files/collections-api/collections.html.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.138.123.208