Back2Basics: The Story of Trait – Part 2

Table of contents
Reading Time: 3 minutes

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.

https://gist.github.com/mahesh2492/912fa3da297660afc96c657815610e2d.js



This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters


trait Animal{
def speak = println("speaking..")
def walk = println("walking fastly..")
def comeToMaster: Unit
}
class Cat extends Animal{
override def speak: Unit = println("meow….")
def comeToMaster = println("catch me if you can..")
}
object Sample extends App{
val kity = new Cat
kity.speak
kity.walk
kity.comeToMaster
}
view raw

Sample.scala

hosted with ❤ by GitHub

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?



This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters


trait Animal{
def speak: Unit
def walk: Unit
def comeToMaster: Unit
}
abstract class AnimalClass extends Animal{
def speak = println("speaking..")
def walk = println("walking fastly..")
}
class Cat extends Animal{
override def speak: Unit = println("meow….")
def comeToMaster = println("catch me if you can..")
}
object ByteCode extends App{
val kity = new Cat
kity.speak
kity.walk
kity.comeToMaster
}

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.

References:

Scala CookBook


knoldus-advt-sticker


Written by 

I am a Software Consultant with experience of more than 1.5 years. I am a Functional Programing i.e Scala and Big Data technology enthusiast.I am a active blogger, love to travel, explore and a foodie.

9 thoughts on “Back2Basics: The Story of Trait – Part 23 min read

  1. In the last code snippet, Cat class extends Animal trait. There is no implementation of walk function. Will this code compile. Shouldn’t Cat class extend AnimalClass?

    1. It will compile. Implementation of walk has been moved to Animal$class.class file. And if you see the bytecode of Cat, You can notice line number 6, invokestatic call to walk method of Animal$class.

      1. Got it, What you were trying to say. Last code snippet i was trying to say what happens behind the scenes. Compiler creates abstract class itself. It has been used to demonstrate only what is happening under the hood.

Comments are closed.

Discover more from Knoldus Blogs

Subscribe now to keep reading and get access to the full archive.

Continue reading