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.
Join the DZone community and get the full member experience.
Join For Free1. 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:
xxxxxxxxxx
trait mytrait {
def myMethod():Unit
val aVal: Int
val myVal = 10
def myImpMethod = { println("I am from trait") }
}
An abstract class with an abstract and non-abstract method and variable:
xxxxxxxxxx
abstract class abstClass {
def myMethod():Unit
val aVal: Int
val myVal = 10
def myImpMethod:Unit = { println("I am from abstClass") }
}
In the main method, trait and abstract class both can't be instantiated.
xxxxxxxxxx
val myTObj = new mytrait //compilation error
val myAObj = new abstClass() //compilation error
Classes that are extending trait or abstract class need to implement the declared methods.
xxxxxxxxxx
class myTClass extends mytrait {
val aVal=10
def myMethod ={ println("I am from myTclass") }
}
class myAClass extends abstClass {
val aVal=10
def myMethod ={ println("I am from myAclass") }
}
3. Differences
3.1 Constructor Parameters
xxxxxxxxxx
trait myTraitWithParam(name: String){}
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
xxxxxxxxxx
trait objectInstanceTrait {
def myObjectMethod = { println("I am from object instance trait") }
}
class myTClass {}
def main(args: Array[String]):Unit={
val classObjWithTrait = new myTClass with objectInstanceTrait
classObjWithTrait.myObjectMethod
}
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.
xxxxxxxxxx
class myClass extends trait1 with trait2{}
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.
xxxxxxxxxx
trait Printer {
def print(msg : String) = println (msg)
}
trait DelimitWithHyphen extends Printer {
override def print(msg : String)= { println("-------------") }
}
trait DelimitWithStar extends Printer {
override def print(msg : String)= { println("*************") }
}
class CustomPrinter extends Printer with DelimitWithHyphen with DelimitWithStar
new CustomPrinter().print("Hello World!")
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
xxxxxxxxxx
trait base{
def baseMethod(s: String):Unit = println(s)
}
trait stack1 extends base{
override def baseMethod(s: String) = println("from stack1")
}
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)()
output =>
from stack1
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.
Opinions expressed by DZone contributors are their own.
Comments