Skip to content
Inheritance and override
step 1/7

Reading — step 1 of 7

Learn

~2 min readClasses and Traits

Scala's class inheritance is single (one base class), but combined with traits and the override keyword, you get a robust polymorphism story. Programming in Scala covers this in chapter 12.

Basic inheritance

class Animal(val name: String) {
  def speak: String = s"$name makes a sound"
}

class Dog(name: String) extends Animal(name) {
  override def speak: String = s"$name barks"
}

val rex = new Dog("Rex")
println(rex.speak)        // Rex barks
  • extends for the parent class
  • (name) after extends Animal(name) calls Animal's primary constructor
  • override is REQUIRED for any non-abstract method override

Forcing override catches typos at compile time — mistype the parent method name and the compiler errors instead of silently creating a NEW method.

abstract — must override

abstract class Shape {
  def area: Double                     // abstract — no body
  def describe: String = s"Shape with area $area"
}

class Circle(radius: Double) extends Shape {
  def area: Double = math.Pi * radius * radius
}

abstract class can't be instantiated. Subclasses must implement abstract members. Members declared without a body are implicitly abstract.

final — prevent further inheritance

final class FinalDog extends Animal("Rex")

class Cat(name: String) extends Animal(name) {
  final override def speak: String = "meow"
}

Default is non-final (different from Kotlin which defaults to final).

sealed — closed hierarchy

sealed abstract class Result
case class Success(value: Int) extends Result
case class Failure(error: String) extends Result
case object Loading extends Result

All subclasses must be in the same file. Compiler can warn on non-exhaustive matches:

def handle(r: Result): String = r match {
  case Success(v) => s"got $v"
  case Failure(e) => s"error: $e"
  // Compiler warns: missing case Loading
}

Foundational for ADTs.

Calling super

class Base {
  def greet: String = "hello"
}

class Sub extends Base {
  override def greet: String = super.greet + " world"
}

With multiple traits, super walks the linearization order. Use super[Trait].method for a specific trait.

Visibility through inheritance

  • protected — accessible from this class AND subclasses (NOT siblings)
  • private — only this class
  • private[this] — even stricter; not accessible to other instances of the same class

Common mistakes

  • Forgetting override keyword — compile error.
  • Sealed without case classes — sealed only helps with exhaustive matching when the hierarchy is closed. Combine with case class for full ADT.
  • Trying to override a final method — compile error.
  • Mixing with and extends orderextends first, then with.

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…