10 Apr 2019 | 3mins
This is the second part of my contribution to Gympass’ Scala study group. Scala for the Impatient, chapter 8: Inheritance.
Inheritance is the mechanism that allows a child class to access properties( defs/ vals/ vars) of its parent classes*.( or traits/ case classes/ abstract classes etc.).
We will learn how inheritance works in Scala. Highlights:
class Employee extends Person {
var salary: 0.0
...
}
We can specify fields and methods that are new to the subclass or that overrides properties of the superclass.
It is possible to declare class final so that cannot be extended. It is also possible to do this to individual methods or fields so it can’t be overridden.
We must use override when you override a method that isn’t abstract
public class Person {
...
override def toString = getClass.getName + "[name=" + name + "]"
}
Invoking a superclass method using super:
public class Employee extends Person {
...
override def toString = super.toString + "[salary=" + salary + "]"
}
Use isInstanceOf to test if an object belongs to a class or a subclass of it. The method asInstanceOf is used to convert an object to a specific subclass.
if (p.isInstanceOf[Employee]) {
val s = p.asInstanceOf[Employee] // s has type Employee
...
}
if you want to test an object to a specific class (without subclasses) use:
if (p.getClass == classOf[Employee])
However, pattern matching is usually better than using type check and casts.
A method or field can be declared as protected and it can be visible only for subclasses, and not throughout the package.
The primary constructor is intertwined with the class definition. The call to the superclass too.
class Employee(name: String, age: Int, val salary : Double) extends Person(name, age)
You can override fields with another field with the same name.
These are the restrictions:
OBS: A var cannot be overridden. If you provide a var, all subclasses will be stuck with it
An anonymous subclass is created when you include a block with definitions or overrides. (Object with structural type) Ex:
val alien = new Person("Fred") {
def greeting = "Greetings, Earthling! My name is Fred."
}
Use abstract to create classes that cannot be instantiated. Used when one or more methods are not defined.
No override needed on subclasses.
An abstract field is a field without an initial value.
No override needed on subclasses.
Construction order problem. Not sure when it occurs…
early definition syntax is used instead of final or lazy
You place the val fields in a block after the extends keyword:
class Bug extends {
override val range = 3
} with Creature

When we write a class we should consider overriding the equals method to provide an accurate representation for our class.
Ex:
Class Item(val description: String, val price: Double)
...
final override def equals(other: Any) = {
val that = other.asInstanceOf[Item]
if (that == null) false
else description == that.description && price == that.price
}
OBS: The equals override only works for parameters with type Any.
OBS2: Do not forget to override the HashCode too. Use only fields you use on equality check.
final override def hashCode = 13 * description.hashCode + 17 * price.hashCode
In a normal application simply use == operator.