Raffi Khatchadourian (based on “Scala for the Impatient” 2nd Edition by Cay Horstmann)
September 22, 2020
extends and final keywords are similar to those in Java.override keyword when you override a method.
@Override annotation in Java.class Person(val name: String) {
override def toString = s"${getClass.getName}[name=$name]"
}
val p = new Person("Juan")
println(p)Outputs:
Person[name=Juan]
protected.Recall that a field in Scala consists of:
You can override a val (or parameterless def) with another val field of the same name.
Then, the subclass will have a private field and a public accessor, which overrides the one from the super class.
class Person(val name: String) {
override def toString = s"${getClass.getName}[name=$name]"
}
class SecretAgent(codename: String) extends Person(codename) {
override val name = "secret"
override def toString = "shh"
}
val s = new SecretAgent("1234")
println(s)Outputs:
shh
Can also override an abstract def with a val:
abstract class Person {
def id: Int // No implementataion, specific to each kind of person.
// ...
}
/**
* A concrete implementation of Person.
*/
class Student(override val id: Int) extends Person {
// The student ID is supplied by the ctor.
// ...
override def toString = s"Student with ID: ${id}"
}
val s = new Student("54321")
println(s)Outputs:
Student with ID: 54321
override keyword not required when providing an implementation for an abstract method.
Can also have abstract fields, i.e., fields without an initial value:
abstract class Person {
val id: Int // No initializer---abstract field and accessor.
var name: String // No initializer---abstract field, accessor, and mutator.
// ...
}class Employee(val id: Int) extends Person { // Has a concrete id property.
var name = "John Doe" // and a concrete name property that can be concretized.
override def toString = s"Employee ${name} with ID: ${id}"
}
val e = new Employee(5)
println(e)Outputs:
Employee John Doe with ID: 5
What if we did not override name? What would happen?
Unit, i.e., (), extend AnyVal.
AnyVal has no methods; it’s just “marker.”AnyRef.
java.lang.Object.Any is the hierarchy root. It defines:
isInstanceOf[]asInstanceOf[]ScalaObject.Null is a singleton type with the value null.
null to any reference.Nothing has no instances.
Scala inheritance hierarchy diagram
NothingUseful for generic constructs.
Nil has the type List[Nothing].List[T] for any T.The method ??? has return type Nothing.
NotImplementedErr.class Person(val name: String) {
def speak() {println(s"My name is ${name}.")}
def description = ???
}
val p = new Person("Sofia")
p.speak() // OK!
println(p.description)Outputs:
My name is Sofia.
scala.NotImplementedError: an implementation is missing ...The eq method of AnyRef checks whether two references refer to the same object.
The equals method in AnyRef calls eq.
When designing your own classes, consider overriding equals method:
Item objects may be “equal” if they have the same description and price.name fields are equal, do the references refer to the same object?
equals method unless there is some other unique identifier.If you do override equals, you must also override hashCode:
## method is a null-safe version of the hashCode method.
null instead of throwing an exception.Don’t call eq or equal from application code. Instead, use ==, which, for reference types, checks for null and calls equals.
A value class:
AnyVal.val) parameter, i.e., the “wrapped” value, and no body.equals and hashCode methods that simply delegate to the wrapped value.