Scala Tutorial

Basics

Control Statements

OOP Concepts

Parameterized - Type

Exceptions

Scala Annotation

Methods

String

Scala Packages

Scala Trait

Collections

Scala Options

Miscellaneous Topics

Scala | Field Overriding

In Scala, fields in classes can't be directly overridden like methods. However, you can simulate field overriding by using underlying methods.

When you define a val or var in a class, Scala generates getter (and setter, in the case of var) methods for that field. Overriding a field in a subclass essentially means overriding the getter (and possibly setter) method of the superclass.

Let's explore this concept with some examples:

Overriding val

If a superclass defines a val, it's generating a getter for that val. A subclass can override this val by defining its own version:

class SuperClass {
  val field: String = "SuperClass"
}

class SubClass extends SuperClass {
  override val field: String = "SubClass"
}

val obj = new SubClass
println(obj.field)  // Outputs: SubClass

Overriding var

When overriding a var, you're overriding both the getter and the setter.

class SuperClass {
  var field: String = "SuperClass"
}

class SubClass extends SuperClass {
  override var field: String = "SubClass"
}

val obj = new SubClass
println(obj.field)  // Outputs: SubClass
obj.field = "Modified"
println(obj.field)  // Outputs: Modified

Overriding abstract fields

Scala allows abstract fields, which means you can define a field in a trait or abstract class without giving it an initial value:

trait TraitWithField {
  val field: String
}

class ConcreteClass extends TraitWithField {
  val field: String = "ConcreteClass"
}

val obj = new ConcreteClass
println(obj.field)  // Outputs: ConcreteClass

Overriding with def

A val can be overridden with a def in a subclass:

class SuperClass {
  val field: String = "SuperClass"
}

class SubClass extends SuperClass {
  override def field: String = "SubClass"
}

val obj = new SubClass
println(obj.field)  // Outputs: SubClass

Caveats:

  1. Initialization Order: Be aware of initialization order when overriding fields. In Scala, superclass fields are initialized before subclass fields. If a superclass field depends on a subclass field, you may run into issues.

  2. Early Definitions: If you encounter initialization order issues, Scala offers a mechanism known as "early definitions" or "early initializers" to adjust the order.

In conclusion, field overriding in Scala isn't direct like method overriding, but thanks to Scala's consistent treatment of fields and methods (i.e., every field has an associated getter method, and mutable fields also have setter methods), field overriding can be achieved by essentially overriding the associated methods.

  1. Overriding Mutable and Immutable Fields in Scala:

    Fields can be either mutable (var) or immutable (val). Both can be overridden in a subclass.

    class Animal {
      val sound: String = "Generic sound"
    }
    
    class Dog extends Animal {
      override val sound: String = "Bark"
    }
    
  2. Visibility Modifiers and Field Overriding in Scala:

    Visibility modifiers can be applied to fields during overriding.

    class Animal {
      protected val sound: String = "Generic sound"
    }
    
    class Dog extends Animal {
      override protected val sound: String = "Bark"
    }
    
  3. Conflict Resolution in Field Overriding in Scala:

    If a subclass inherits from multiple classes with the same field name, conflicts can arise. Use super to disambiguate.

    trait A { val x: Int = 1 }
    trait B { val x: Int = 2 }
    class C extends A with B {
      override val x: Int = super[A].x + super[B].x
    }
    
  4. Field Overriding vs. Method Overriding in Scala:

    Field overriding is different from method overriding. Fields are accessed without parentheses, while methods require them.

    class Animal {
      def sound(): String = "Generic sound"
    }
    
    class Dog extends Animal {
      override def sound(): String = "Bark"
    }
    
  5. Using 'super' Keyword in Field Overriding:

    The super keyword is used to access the overridden field in the superclass.

    class Animal {
      val sound: String = "Generic sound"
    }
    
    class Dog extends Animal {
      override val sound: String = "Bark" + super.sound
    }
    
  6. Abstract Fields and Concrete Implementation in Scala:

    Abstract fields in a trait or abstract class can be overridden with concrete implementations in a subclass.

    trait Animal {
      val sound: String
    }
    
    class Dog extends Animal {
      val sound: String = "Bark"
    }