{{announcement.body}}
{{announcement.title}}

The Practical Difference Between Abstract Class and Trait in Scala

DZone 's Guide to

The Practical Difference Between Abstract Class and Trait in Scala

Take a look at what the actual differences are between abstract class and trait in Scala.

· Microservices Zone ·
Free Resource

1. Overview

Before getting to know the difference between abstract class and trait lets understand them.

Traits are like Java interface but in a trait, we are allowed to implement its members.

Abstract Classes are constructed using abstract keyword, it supports both abstract and non-abstract methods.

2. Similarities

Once we understand similarities then only we can appreciate the differences. Let's go ahead and learn those.

A trait with a declared and implemented method and variable:

Scala
 




xxxxxxxxxx
1


1
trait mytrait { 
2
  def myMethod():Unit
3
  val aVal: Int 
4
  val myVal = 10 
5
  def myImpMethod = { println("I am from trait") } 
6
}


An abstract class with an abstract and non-abstract method and variable:

Scala
 




xxxxxxxxxx
1


 
1
abstract class abstClass { 
2
  def myMethod():Unit 
3
  val aVal: Int 
4
  val myVal = 10 
5
  def myImpMethod:Unit = { println("I am from abstClass") } 
6
}


In the main method, trait and abstract class both can't be instantiated.

Scala
 




xxxxxxxxxx
1


 
1
val myTObj = new mytrait //compilation error
2
val myAObj = new abstClass() //compilation error


Classes that are extending trait or abstract class need to implement the declared methods.

Scala
 




xxxxxxxxxx
1


 
1
class myTClass extends mytrait {
2
  val aVal=10 
3
  def myMethod ={ println("I am from myTclass") } 
4
} 
5
class myAClass extends abstClass {
6
  val aVal=10 
7
  def myMethod ={ println("I am from myAclass") } 
8
}


3. Differences

3.1 Constructor Parameters

Scala
 




xxxxxxxxxx
1


1
trait myTraitWithParam(name: String){} 
2
abstract class abstClassWithParam(name : String){}


name is the constructor parameter, a trait with a constructor parameter gives compilation error whereas it works fine with an abstract class.

3.2 Adding to Object Instance

Scala
 




xxxxxxxxxx
1


 
1
trait objectInstanceTrait { 
2
  def myObjectMethod = { println("I am from object instance trait") } 
3
} 
4
class myTClass {} 
5
def main(args: Array[String]):Unit={ 
6
  val classObjWithTrait = new myTClass with objectInstanceTrait
7
  classObjWithTrait.myObjectMethod 
8
} 
9
ouptput => "I am from object instance trait"


The implemented method "myObjectMethod" from the trait can be accessed by an instance of a class. Abstract class can't be added to an object instance, it leads to a compilation error.

3.3 Multiple Inheritances

In multiple inheritance, one class can have more than one superclass and inherit features from all parent classes. Scala does not support multiple inheritance with classes, but it can be achieved by traits.

Scala
 




xxxxxxxxxx
1


1
class myClass extends trait1 with trait2{} 
2
class myNewClass extends abstClass1 with abstClass2{}


When abstract class used for multiple inheritances, it results in a compilation error.

With multiple inheritance, the scala resolves the diamond problem, by trait linearization. A trait with the extreme right will get the highest priority.

Scala
 




xxxxxxxxxx
1
15


1
trait Printer { 
2
  def print(msg : String) = println (msg) 
3
 } 
4
trait DelimitWithHyphen extends Printer { 
5
  override def print(msg : String)= { println("-------------") } 
6
} 
7
trait DelimitWithStar extends Printer { 
8
  override def print(msg : String)= { println("*************") } 
9
} 
10
 
          
11
class CustomPrinter extends Printer with DelimitWithHyphen with DelimitWithStar 
12
 
          
13
new CustomPrinter().print("Hello World!") 
14
  
15
 output=> "*************"


3.4 Stackability

Stackable traits in Scala refers to being able to mix in multiple traits that work together to apply multiple modifications to a method. This involves invoking super.theMethod

Scala
 




xxxxxxxxxx
1
22


1
trait base{ 
2
  def baseMethod(s: String):Unit = println(s) 
3
}
4
 
          
5
trait stack1 extends base{
6
  override def baseMethod(s: String) = println("from stack1") 
7
} 
8
trait replace1 extends base { 
9
  abstract override def baseMethod(s: String) ={
10
    super.baseMethod(s); 
11
    println("from replace1")} 
12
}
13
class Stackable { 
14
  this : base => def apply() 
15
  { println( baseMethod("bottom") ) } 
16
} 
17
 
          
18
(new Stackable with stack1 with replace1)() 
19
 
          
20
output => 
21
from stack1 
22
from replace1


Invocation started from relace1 then it is passed to stack1 by super.baseMethod(s).

This method invocation went to stack1 because it is left side of replace1.

3.5 Interoperable with Java

Traits are interoperable with Java if they don't have any implementation, abstract classes can be directly used.

4. Conclusion

Scala traits are more flexible than abstract classes. We should use abstract classes when we want to create a base class with a constructor argument. In case of dought always go with the trait, because traits can be easily converted into an abstract class.

Topics:
abstract classes, differences and similarities, scala, trait

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}