Friday, September 16, 2016

Method Overloading & Implicit Conversion : Example

scala> class Subject(name: String, mark: Int) { //#153
     |
     |    //Specify Precondition for the Primary Constructor
     |    require(mark >= 0)
     |    val mName = name //Class parameter is not accessible to outside world
     |                     //So we are creating new member variables
     |    val mMark = mark
     |    // An Auxiliary Constructor that takes one Parameter
     |    def this(name: String) = {
     |       // First Line should always be Primary Constructor or
     |       // another Auxiliary Constructor
     |       this(name, 50) //Here we are calling the Primary Consructor
     |       println("Inside Auxiliary Consructor...")
     |    }
     |    // Override an existing Method
     |    // Is a best practice to override toString()
     |    // for debugging purpose  #138
     |    override def toString() = {
     |       name + ", " + mark
     |    }
     |
     |    def +(samesubject: Subject):Subject = {
     |       require(mName == samesubject.mName)
     |       val newMark = mMark + samesubject.mMark
     |       new Subject(mName, newMark)
     |    }
     |
     |    def + (tpl: (String, Int)) : Subject = {
     |       require(mName == tpl._1)
     |       val newMark = new Subject(tpl._1, tpl._2)
     |       newMark + this
     |    }
     | }
defined class Subject

scala>

scala> val subject = new Subject("math", 40)
subject: Subject = math, 40

scala> val added1 = subject + new Subject("math", 20)
added1: Subject = math, 60

scala> val added2 = added1 + ("math", 5)
added2: Subject = math, 65

scala> // This do not work. We will need Implicit Conversion

scala> val added3 = ("math", 5) + added2
<console>:17: error: overloaded method value + with alternatives:
  (tpl: (String, Int))Subject(in object $iw)(in object $iw)(in object $iw)(in object $iw) <and>
  (samesubject: Subject(in object $iw)(in object $iw)(in object $iw)(in object $iw))Subject(in object $iw)(in object $iw)(in object $iw)(in object $iw)
 cannot be applied to (Subject(in object $iw)(in object $iw)(in object $iw)(in object $iw))
       val added3 = ("math", 5) + added2
                                ^

scala>

scala> implicit def TupleToSubject(tpl: (String, Int)): Subject = {
     |    new Subject(tpl._1, tpl._2)
     | }
<console>:14: warning: implicit conversion method TupleToSubject should be enabled
by making the implicit value scala.language.implicitConversions visible.
This can be achieved by adding the import clause 'import scala.language.implicitConversions'
or by setting the compiler option -language:implicitConversions.
See the Scala docs for value scala.language.implicitConversions for a discussion
why the feature should be explicitly enabled.
       implicit def TupleToSubject(tpl: (String, Int)): Subject = {
                    ^
TupleToSubject: (tpl: (String, Int))Subject

scala>

scala> // This works now using Implicit Conversion

scala> // as long as the Implicit Function is in Access Scope

scala> val added3 = ("math", 5) + added2
added3: Subject = math, 70