Overview

Inheritance is a cornerstone of OOP and Scala has support for this concept. A Scala class can extend one and only one other class. This is similar to Java. We can do this using the extends keyword.

Inheritance 1

Class inheritance is the common way for achiving polymorphism. A Scala class can extend one and only one other class. This is similar to Java. We can do this using the extends keyword.

class Element(id: Int){
}
defined class Element
class Triangle(id: Int) extends Element(id){
    def elementType: String = "TRI"
}
defined class Triangle

Similar to Java, we can declare a class final so that it cannot be extended. However, unlike Java, you can also declare individual methods or fields final so that they cannot be overridden [1].

Overriding methods

Child classes can customize the behaviour of methods from the parent classes (provided of course these are not decaled final). This however should be told explicitly using the override modifier

class Element(id: Int){
    def elementType: String = "INVALID";
}
defined class Element
class Triangle(id: Int) extends Element(id){
    def elementType: String = "TRI"
}
cmd3.sc:2: `override` modifier required to override concrete member:
def elementType: String (defined in class Element)
    def elementType: String = "TRI"
        ^Compilation Failed
Compilation Failed
class Triangle(id: Int) extends Element(id){
    override def elementType: String = "TRI"
}
defined class Triangle
val tri = new Triangle(10)
tri: Triangle = ammonite.$sess.cmd3$Helper$Triangle@1266c3c3
print(tri.elementType)
TRI

This requirement can potentially be very useful [1]:

  • When we misspell the name of the method that we are overriding
  • When we accidentally provide a wrong parameter type in the overriding method
  • When we introduce a new method in a superclass that clashes with a subclass method

As a final note, we can invoke a superclass method in Scala works in the same way we do in Java that is using the keyword super

class TriQuad(id: Int) extends Triangle(id){
    
    override def elementType: String = super.elementType + "_QUAD"
}
defined class TriQuad
val quad = new TriQuad(10)
quad: TriQuad = ammonite.$sess.cmd6$Helper$TriQuad@69fd55e1
print(quad.elementType)
TRI_QUAD

isInstanceOf

Frequently, we want to know is an object is an instance of a class. To do so we can use the isInstanceOf method [1]

val q1 = new TriQuad(1)
q1: TriQuad = ammonite.$sess.cmd6$Helper$TriQuad@31d67ba6
if(q1.isInstanceOf[TriQuad]) println("This is TRI_QUAD")
This is TRI_QUAD

The q1.isInstanceOf[TriQuad] will succeed if q1 refers to an object of class TriQuad. Since TriQuad is a subclass of Element the following also succeeds

if(q1.isInstanceOf[Element]) println("This is TRI_QUAD")
This is TRI_QUAD

inst.isInstanceOf[Type] returns false if inst is null:

val q2 = null
q2: Null = null
if(q2.isInstanceOf[Element]) println("This is TRI_QUAD") else println("Object is null")
Object is null

We can further use the asInstanceOf to convert a reference to a subclass reference:

val q2 = q1.asInstanceOf[Element]
q2: Element = ammonite.$sess.cmd6$Helper$TriQuad@31d67ba6
print(q2.elementType)
TRI_QUAD

If q2 is not an Element , then we get an exception

class SomeClass{}
defined class SomeClass
val q2 = new SomeClass
q2: SomeClass = ammonite.$sess.cmd16$Helper$SomeClass@3f85fd8
val q3 = q2.asInstanceOf[Element]
java.lang.ClassCastException: class ammonite.$sess.cmd16$Helper$SomeClass cannot be cast to class ammonite.$sess.cmd2$Helper$Element (ammonite.$sess.cmd16$Helper$SomeClass and ammonite.$sess.cmd2$Helper$Element are in unnamed module of loader ammonite.runtime.SpecialClassLoader @7bd4937b)
  ammonite.$sess.cmd18$Helper.<init>(cmd18.sc:1)
  ammonite.$sess.cmd18$.<clinit>(cmd18.sc:7)

If we want to test whether an instance refers to a specific class, but not a subclass, we can use classOf [1]

if (p.getClass == classOf[Element])

The classOf method is defined in the scala.Predef object that is always imported.

References

  1. Cay Horstmann, Scala for the Impatient 1st Edition