In our previous blog The Story of Trait – Part 1, we have discussed how traits are the just regular interfaces at the very basic form. In this blog, we will explore about traits can have method implementation too.
We will continue with our previous example and modify it and see how trait behaves in different scenarios.
Here we have implemented two method and other method is abstract in trait Animal and class Cat will extend it and give an implementation of abstract method comeToMaster. Let’s see how trait looks now under the hood.
If you take a trait with an implementation in it, it quickly becomes two things instead of one i.e an interface and an abstract class as well.
After compiling Sample.scala, use ls for .class files. And you will notice there will be two class files for Animal i.e Animal.class, Animal$class.class.
If you take a look at them, Animal class will have an interface and Animal$class will have abstract base class. Let see first Animal.class, that should be an interface.
Oh! , wait a minute, this does not show the interface, it is an abstract class. And if you see the Animal$class it will show the same bytecode as above. What exactly is happening?
Let’s dig deeper, we are being fooled by the tool. Let’s remove the Animal$class.class and now we are having only Animal.class.
Now you can see how the tool is fooling us. In Animal.class file, there is an interface. And All methods become abstract in interface i.e speak, walk, comeToMaster. We know that speak and walk have already implemented and the only comeToMaster is truly abstract in a trait.
What exactly happens at the bytecode level?
We can think about it slightly differently, we can provide our implemented method in abstract AnimalClass. In other words, when we give the implementation in a trait.
What Scala does under the hood, it moves an implementation to an abstract base class and keeps the trait as an interface all the way.
Let’ see the bytecode of Cat class,
Notice, Cat class implements the Animal trait. However, it does implement the walk method. walk method makes an invokestatic call to walk method of abstract class Animal$class. Since we have overridden method speak in Cat, so it won’t make an invokestatic call to an abstract class.
So, we saw how trait behaves when it has an implemented methods also and how things work under the hood. In our next blog The Story of Trait – Part 3, we will see the mixin of traits. Till then Stay tuned 🙂
Please feel free to suggest and comment.