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).