Sunday 17 December 2017

Introduction to Scala - IV

We continue with more Scala on the topic of Traits in this post. For all the work in this post, we will use Read-Evaluate-Print-Loop Scala interpreter. Some familiarity with Java will be of great help in understanding Scala. In this post, we will look at the way traits are declared and how traits are called in programs.

Traits can be seen as abstract classes in Scala. Like in Java, a concrete class that extends a trait must implement all methods in the trait definition. Like in Java, traits cannot be instantiated. An example can be seen below:

trait trait1 { def method1 }
trait trait2 { def method2 }
trait trait3 { def method3 }

class TraitImplementation extends trait1 with trait2 with trait3{
def method1 { println ("In method1") }
def method2 { println ("In method2") }
def method3 { println ("In method3") }
}

val TraitImplementation1 = new TraitImplementation
TraitImplementation1.method1
TraitImplementation1.method2
TraitImplementation1.method3


The results are shown below:

scala> trait trait1 { def method1 }
defined trait trait1

scala> trait trait2 { def method2 }
defined trait trait2

scala> trait trait3 { def method3 }
defined trait trait3

scala> class TraitImplementation extends trait1 with trait2 with trait3{
     | def method1 { println ("In method1") }
     | def method2 { println ("In method2") }
     | def method3 { println ("In method3") }
     | }
defined class TraitImplementation

scala> val TraitImplementation1 = new TraitImplementation
TraitImplementation1: TraitImplementation = TraitImplementation@6ee88e21

scala> TraitImplementation1.method1
In method1

scala> TraitImplementation1.method2
In method2

scala> TraitImplementation1.method3
In method3


Three traits are defined having a method definition each. The concrete class called TraitImplementation extends trait1 with keyword extends. But, for inheriting the next traits, we use the with keyword. The three methods are implemented in the class. After that, the class is instantiated, the three methods can be called.

If we try to instantiate a trait, we get below error:

scala> new trait1
<console>:13: error: trait trait1 is abstract; cannot be instantiated
       new trait1
       ^


In case the member names are the same, then, the override keyword has to be used in the class extending the trait as shown below:

trait trait4 { def method4 { println("method4 in trait4") }}

class TraitImplementation extends trait4 {
override def method4 { println("method4 in TraitImplementation") }
}

val TraitImplementation1 = new TraitImplementation
TraitImplementation1.method4


The results are shown below:

scala> trait trait4 { def method4 { println("method4 in trait4") }}
defined trait trait4

scala> class TraitImplementation extends trait4 {
     | override def method4 { println("method4 in TraitImplementation") }
     | }
defined class TraitImplementation

scala> val TraitImplementation1 = new TraitImplementation
TraitImplementation1: TraitImplementation = TraitImplementation@2a136383

scala> TraitImplementation1.method4
method4 in TraitImplementation


As expected, the method overridden in the class is called. If, however, we need the method in the trait to be called, we have to use the super keyword as shown below:

trait trait5 { def method5 { println("method5 in trait5") }}

class TraitImplementation extends trait5 {
override def method5 { super[trait5].method5 }
}

val TraitImplementation1 = new TraitImplementation
TraitImplementation1.method5


The results are shown below:

scala> trait trait5 { def method5 { println("method5 in trait5") }}
defined trait trait5

scala> class TraitImplementation extends trait5 {
     | override def method5 { super[trait5].method5 }
     | }
defined class TraitImplementation

scala> val TraitImplementation1 = new TraitImplementation
TraitImplementation1: TraitImplementation = TraitImplementation@8f39224

scala> TraitImplementation1.method5
method5 in trait5


Now, the method in the parent trait is called.

This concludes the discussion on Traits in Scala.