Traits in Scala- Deep Dive

Traits are units of code reuse in Scala. Traits encapsulates methods and field definitions. Their role is similar to that of interfaces in Java- A workaround for Multiple Inheritance. But unlike Interfaces they can have method and field definitions. More features will be explained in the article.

Defining Traits:

A trait definition looks like a class definition but uses the keyword “trait.

trait Bounceable{

     def bounce():String="Bounce Method in Trait"

}

The above declared trait has a concrete method. The ability to declare concrete methods in an trait gives default implementation option. In interfaces one has to write/copy-paste the default declaration in each class which implements the interface or declare a class that implements that interface and let other classes extend the concrete class. The first method has code repition and the second method has the restriction that a class can extend only one class. So this feature of “trait” stands out best.

As in Java a class implements interface, in Scala classes traits are mixed into a class. This is done using either extends or “with” keywords.

class Ball(s: Int) extends Bouncable{

      var size:Int

      override def toString():String= Integer.toString(size)

}

In the above example we are using extends to mix in the trait- Here Ball is implicitly inherits trait’s superclass which is “AnyRef”. Lets try to use the class Ball to test the mixed in trait.

object Test{

           def main(args:Array[String])={

                    var ball = new Ball(33)

                    var ball2:Bounceable= new Ball(400)

                    println(ball.bounce()) //This prints "Bounce Method in Trait"

                    println(ball) //This prints "33"

                    println(ball2.bounce())

                    println(ball2)

         }

}

Note: Output written as comment.

Regarding the ball2 instance being declared as type “Bounceable”. Its a valid declaration cause supertype references can refer to the instances of its subtypes. But they cannot access the methods/fields declared by the subtypes (different with the overriding case).

Read more