(11) Traits

About

:octocat: GitHub: All of the example code: repo (link)

:page_facing_up: blog link: https://purrgramming.life/cs/programming/fp/ :star:


Motivation

In Java, as well as in Scala, a class can only have one superclass.

But what if a class has several natural supertypes to which it conforms or from which it wants to inherit code? Here, you could use traits.

Classes, objects and traits can inherit from at most one class but many arbitrary traits.

Scala Trait vs Java Interface

Traits define reusable interfaces and behavior, including abstract/concrete members and state. Java interfaces also support default methods; the distinction is not simply whether methods can have implementations. Scala 2 traits have no constructor parameter lists; Scala 3 adds trait parameters.

Similarly to Java, in Scala, it is possible to

  • have only one superclass
  • can extend multiple traits (interfaces in Java)

Usage

Traits are similar to interfaces in Java and are created using trait keywords.

But what if a class has several natural supertypes to which it conforms or
from which it wants to inherit code?

Here, you could use traits.

A trait is declared like an abstract class, just with a trait instead of
abstract class


// Creating a super class  
abstract class Shapes {  
  def draw() = println("Draw the shape")  

  // Overload  
  def draw(id: Int) = println(s"Draw the shape (Id: $id)")  
}  

trait MathShape {  
  def size: Unit  
}  

// Creating a subclass  
class Rectangle extends Shapes with MathShape {  
  def size = println("length (L) * width (W) ")  
}  

// Creating a subclass  
class Circle extends Shapes with MathShape {  
  // Overriding  
  override def draw() = println("Draw the Circle")  

  // Override, Overload  
  override def draw(id: Int) = println(s"Draw the Circle (Id: $id)")  

  def size = println("pi * radius^2 ")  
}  

val rectangle = new Rectangle  
rectangle.draw()  
rectangle.draw(0)  
rectangle.size  

val circle = new Circle  
circle.draw()  
circle.draw(1)  
circle.size

Abstract Class vs Trait

Background reference: https://drek4537l1klr.cloudfront.net/sfregola/v-2/Figures/11_02.png

file

Question Trait Abstract class
Composition A class can mix in multiple traits, subject to compatible members. A class can extend only one class.
When composed At class definition or object construction; not retrofitted onto an already-created instance. Chosen through class inheritance, also not retrofitted.
Constructor parameters Supported in Scala 3; not in Scala 2. Supported in both Scala 2 and 3.
Dispatch Overridable instance methods use dynamic dispatch; linearization determines mixin order and super resolution. Overridable instance methods also use dynamic dispatch.
Java interop Depends on Scala version and generated API; check how Java callers construct/implement it. Often straightforward for shared constructor-based APIs, but still subject to types, visibility and compiler-generated details.

Takeaway

Use traits to compose capabilities and an abstract class when a shared base class and constructor are appropriate. Neither choice makes ordinary overridden methods statically bound.

References: Scala traits; Scala 3 trait parameters.

Leave a Reply

Your email address will not be published. Required fields are marked *