I am new in Scala and I am referring book "Scala for Impatient - Second Edition".
I am working on a small code where I have created a class Fraction
which as two Int fields num
(number) and den
(denominator). The class has a method *
which performs multiplication of num
and den
and returns new Fraction
instance.
Here, for understanding the working of implicit
, I have created an object FractionConversions
which helps with two implicit method intToFraction
and fractionToDouble
.
While testing the code in ImplicitConversionTester
, I have imported the FractionConversions._
path, so both of the implicit methods are available to compiler.
Now, refer the code to make the picture more clear.
package OperatorOverloadingAndImplicitConversion
class Fraction(n : Int, d : Int) {
private val num = this.n
private val den = this.d
def *(other : Fraction) = new Fraction(num*other.num, den*other.den)
override def toString: String = {
s"Value of Fraction is : ${(num*0.1)/den}"
}
}
object Fraction {
def apply(n: Int, d: Int): Fraction = new Fraction(n, d)
}
object FractionConversions {
implicit def fractionToDouble(f : Fraction): Double = {
println("##### FractionConversions.fractionToDouble called ...")
(f.num*0.1)/f.den
}
implicit def intToFraction(n : Int) : Fraction = {
println("##### FractionConversions.intToFraction called ...")
new Fraction(n,1)
}
}
object ImplicitConversionTester extends App {
import FractionConversions._
/*
* CASE 1 : Here, "fractionToDouble" implicit is called.
Why "intToFraction" was eligible but not called ?
*/
val a = 2 * Fraction(1,2)
/*
* CASE 2 : Works as expected.
Here, number "2" is converted to Fraction using "intToFraction" implicit.
*/
val b = 2.den
/*
* CASE 3: Why again "intToFraction" but not "fractionToDouble" ? Why ?
*/
val c = Fraction(4,5) * 3
println(a) // output : 0.1 FractionConversions.fractionToDouble called
println(b) // output : 1 FractionConversions.intToFraction called
println(c) // output : Value of Fraction is : 0.24000000000000005. FractionConversions.intToFraction called
}
I have query in above code :
Case#1 : For statement
val a = 2 * Fraction(1,2)
, WhyfractionToDouble
implicit is getting called here even thoughintToFraction
is also eligible in this case ?case#3 : For statement
val c = Fraction(4,5) * 3
, whyintToFraction
called ? WhyfractionToDouble
was not used ?
Here, I tried to replicate the following scenario mentioned in the book, so above question arises.
So, should We summarise that, the compiler avoids converting the left side operand and select the right side to convert if both of them are eligible for conversion ? For example, In case of (a*b)
, a is always ignored and b is converted to expected type even though a
and b
both are eligible for conversion ?