Difference Between Abstract Class and Trait in Scala

Knoldus Blog Audio
Reading Time: 4 minutes

In this blog we’ll go through the practical difference between the Abstract class and Trait in Scala.

I. OVERVIEW

Firstly, Let me give you a brief introduction on what Abstract class and Traits are in Scala. After that we’ll start with the differentiation.

ABSTRACT CLASS

Abstraction means hiding the internal details and showing only the functionality. And, In Scala abstraction is achieved by using abstract class. We can construct abstract class by using the abstract keyword. It can contain both abstract and non-abstract(concrete methods) methods. Above all, A class can extend only one abstract class.

Syntax:

abstract class class_name
{
// code..
}

TRAIT

Trait are like Interfaces in Java with partial implementation. We can construct trait by using the trait keyword. Further In Scala, Trait can have abstract and non-abstract(concrete methods) methods. In addition, You can create trait that can have all abstract methods or some abstract and some non-abstract methods.

Syntax:

trait Trait_Name{
// Fields..
// Methods..
}

II. SIMILARITIES

So, now let’s try our hands on the similarities between Abstract classes and Traits with examples.

  1. Both Abstract class and Trait cannot be instantiated.
//abstract class creation
abstract class myAbstractClass { 
  
  //abstract method ( no implementation defined )
  def myAbstractMethod()
  
  //concrete method
  def myImplMethod(): Unit ={
    println("Happy Learning!!!!")
  }
}

//created object to invoke abstract class
object main extends App{

  //below statement will give you a compile-time error i.e., cannot be instantiated
  val myAbstractClassObject = new myAbstractClass 
//trait creation
trait myTrait {

  //abstract method ( no implementation defined )
  def myAbstractMethod()

  //concrete method
  def myImplMethod(): Unit ={
    println("Happy Learning!!!!")
  }
}

//created object to invoke trait
object main extends App{

  //below statement will give you a compile-time error i.e., cannot be instantiated
  val myTraitObject = new myTrait
}

2. Moreover, classes that extend abstract class and trait need to implement the abstract methods declared.

abstract class myAbstractClass {

  //abstract method ( no implementation defined )
  def myAbstractMethod()

  //concrete method
  def myImplMethod(): Unit ={
    println("Happy Learning!!!!")
  }
}

//creating a class to over-ride the abstract methods
class myClass extends myAbstractClass{

  override def myAbstractMethod(): Unit = {
    println("Abstract method implemented here..")
  }
}

object main extends App{
  
  val myClassObject = new myClass
  
  myClassObject.myAbstractMethod()  //OUTPUT - Abstract method implemented here..
  myClassObject.myImplMethod()  //OUTPUT - Happy Learning!!!!
}
//Trait defined
trait myTrait {

  //abstract method ( no implementation defined )
  def myAbstractMethod()

  //concrete method
  def myImplMethod(): Unit ={
    println("Happy Learning!!!!")
  }
}

//creating a class to over-ride the abstract methods
class myClass extends myTrait{

  override def myAbstractMethod(): Unit = {
    println("Abstract method implemented here..")
  }
}

//created object to invoke trait
object main extends App{
  
  val myClassObject = new myClass

  myClassObject.myAbstractMethod()  //OUTPUT - Abstract method implemented here..
  myClassObject.myImplMethod()  //OUTPUT - Happy Learning!!!!
}

III. DIFFERENCES

So, now, Let’s see the differences between Abstract classes and Traits with the help of examples :

  1. In Scala, Multiple Inheritance is supported by Traits but not by Abstract classes.

In multiple inheritance, one class can have more than one super-class and inherit features from all parent classes.

As you can see in the below example, Scala does not support multiple inheritance with classes, but it can be achieved by traits. And, when abstract class use multiple inheritance it results in compilation error.

Note : With multiple inheritance, the Scala resolves the diamond problem, by linearization of classes and traits that are mixed into a class. When you have multiple traits inherited, during instantiation(object creation) Scala forms the linear order of classes and traits inherited as per the linearization rule.
//defining trait one
trait myTraitOne{
  def addition(valueOne : Int, valueTwo : Int): Int
}

//defining trait two
trait myTraitTwo{
  def subtraction(valueOne : Int, valueTwo : Int): Int
}

//extending both the traits in below class
class myClass extends myTraitOne with myTraitTwo{

  //method to add two integers value
  override def addition(valueOne: Int, valueTwo: Int): Int = {
    valueOne + valueTwo
  }

  //method to subtract two integers value
  override def subtraction(valueOne: Int, valueTwo: Int): Int = {
    valueOne - valueTwo
  }
}

object main extends App{

  val myClassObject = new myClass

  myClassObject.addition(20,10)  //OUTPUT - 30
  myClassObject.subtraction(20,10) // OUTPUT - 10
}
//defining abstract class one
abstract class myAbstractClassOne{
def addition(valueOne : Int, valueTwo : Int): Int
}

//defining abstract class two
abstract class myAbstractClassTwo{
def subtraction(valueOne : Int, valueTwo : Int): Int
}

//ERROR will occur here when you try to extend two abstract classes together
class myClass extends myAbstractClassOne with myAbstractClassOne{

//method to add two integers value
override def addition(valueOne: Int, valueTwo: Int): Int = {
valueOne + valueTwo
}

//method to subtract two integers value
override def subtraction(valueOne: Int, valueTwo: Int): Int = {
valueOne - valueTwo
}
}

2. Abstract class are not allowed to add an abstract class to an object instance. On the other hand, Traits are allowed to add a trait to an object instance.

For example, you can see the implemented method “display” from the trait can be accessed by an instance of a class. However, Abstract class can’t be added to an object instance, it leads to a compilation error.

trait myTrait{
  def display(): Unit ={
    println(" I am display method defined under the Trait.")
  }
}

class myClass{} //Empty class declaration

object main extends App{

  val myClassObject = new myClass with myTrait //Trait can be accessed by an instance of a class
  myClassObject.display() //OUTPUT -  I am display method defined under the Trait.
}
abstract class myAbstractClass{
def display(): Unit ={
println(" I am display method defined under the Trait.")
}
}

class myClass{} //Empty class declaration

object main extends App{

val myClassObject = new myClass with myAbstractClass //ERROR - needs to be trait to be mixed in
myClassObject.display() //OUTPUT - I am display method defined under the Trait.
}

3. Constructor parameters is supported by Abstract classes but not by Traits in Scala 2.

For example, “empId” constructor parameter in abstract class works absolutely fine while in Traits gives a compilation error.

trait myTrait(empId: Int){ //Traits cannot have parameters
  def display(): Unit ={
    println("Trait with parameters.")
  }
}
abstract class myAbstractClass(empId: Int){ //Abstract classes can have parameters
def display(): Unit ={
println("Abstract class with parameters.")
}
}

Note: Above all, Scala 3 allows traits to have parameters, just like classes have parameters.

trait myTrait(empId: Int) {
    def myMethod(empName: empId): String
}

4. In addition, Abstract class is not stack-able but Traits are.

trait base{ 
def baseMethod(s: String):Unit = println(s) 
}

trait stack1 extends base{
  override def baseMethod(s: String) = println("from stack1") 

} 
8
trait replace1 extends base { 
  abstract override def baseMethod(s: String) ={
  super.baseMethod(s); 
  println("from replace1")} 
}

class Stackable { 
  this : base => def apply() 
  { println( baseMethod("bottom") ) } 
} 

(new Stackable with stack1 with replace1)() 

5. Abstract class are completely interoperable with Java code. On the other hand, Traits are completely interoperable only when they do not contain any implementation code.

In conclusion, I hope you learned the practical difference between the Abstract Class and Trait.

HAPPY LEARNING !! 🙂

References

https://dzone.com/articles/the-practical-difference-between-abstract-class-an

Knoldus-blog-footer-image