In this blog, we will have a look at traits in Scala.
We have classes in Scala. Suppose we have a class Dog which has a method speak.
Now if we want another class Cat which has the same method speak. What we will do?
In Java, generally, we create an interface Animal and classes Dog and Cat will implement the interface. But wait a minute, Scala has no interfaces.
If we try to create an interface Animal which has an abstract method speak, it will throw an error.
Gosh! How we can survive without an interface? Wait a minute, Scala has interfaces but they are not called as an interface, they are called as traits. Let’s try again creating an Animal as a trait.
Notice this time, there is no error.
So, What is a trait?
At the very basic form, traits are interfaces. Though they are more powerful than interfaces. A trait offers mixins. It is a behaviour that can be mixed into or assimilated into a class hierarchy. So, traits can also have implementations. We will explore them in future blogs.
So, for now, let’s understand how traits are just interfaces.
We have already seen above code worked without an error. Let’s explore this little further. After compiling it, if you see the bytecode generated by Scala Compiler
So, what we found that Animal is actually an interface. Remember, we have written Animal as a trait. But under the hood, it is simply an interface with an abstract method speak because speak is an abstract method and as it returns unit so it became a void method. So, you can see in case of Scala how traits are just interfaces on the JVM.
Now continue with our Dog example,
Here, we have Dog and Cat class which extends from Animal and provided the implementation of speak. It is working fine. Let’s see the bytecode generated for classes by Scala Compiler.
Notice even we have used the word extends while extending Animal trait in Dog, implements is not used in class. Despite that, replacement of extend at the bytecode level is still implements. That’s because Scala compiler knows that Animal is a trait meaning it’s an interface. So, Dog implements the interface named Animal.
Let’s play with it more, Animal could either be Pet or Wild.
Now let’s see the bytecode of Pet generated by Scala Compiler,
Notice this time Pet extends Animal because, in Java, interface extends from other interfaces not implement them. So, we can see it is very consistent with the bytecode when Scala generates the bytecode.
We have seen that at the very minimum, traits are just an interface. But it is a lot more than an interface. In next blog The Story of Trait – Part 2 , we will see traits can have implementation too and how they behave under the hood.
For the complete example, the entire code is available on GitHub.
Please feel free to suggest and comment!