Scala Tutorial
Basics
Control Statements
OOP Concepts
Parameterized - Type
Exceptions
Scala Annotation
Methods
String
Scala Packages
Scala Trait
Collections
Scala Options
Miscellaneous Topics
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:
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
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
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
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
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.
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.
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" }
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" }
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 }
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" }
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 }
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" }