The latest instance of the course can be found at: O1: 2024

Luet oppimateriaalin englanninkielistä versiota. Mainitsit kuitenkin taustakyselyssä osaavasi suomea. Siksi suosittelemme, että käytät suomenkielistä versiota, joka on testatumpi ja hieman laajempi ja muutenkin mukava.

Suomenkielinen materiaali kyllä esittelee englanninkielisetkin termit.

Kieli vaihtuu A+:n sivujen yläreunan painikkeesta. Tai tästä: Vaihda suomeksi.

# Chapter 7.3: Inheritance and Class Hierarchies

Questions Answered: Say I have a regular class; how can I define a subtype for it? How do the classes and traits of the Scala API form a family tree? How can I form such a family tree of data types for my program?

Topics: Inheritance: extending a superclass with subclasses. Some key classes in Scala’s class hierarchy. Abstract classes.

What Will I Do? Read and program.

Rough Estimate of Workload:? Three hours or more.

Points Available: B70.

Related Modules: Subtypes.

## Introduction

In the previous chapter, we used traits to define supertypes for multiple classes. In this chapter, we’ll use a technique known as inheritance (periytyminen) that defines supertypes as regular classes rather than traits.

## Let’s Continue with Shapes

In the previous chapter, we defined the trait `Shape` and an implementing class `Rectangle`:

```trait Shape {

def isBiggerThan(another: Shape) = this.area > another.area

def area: Double

}
```
```class Rectangle(val sideLength: Double, val anotherSideLength: Double) extends Shape {

def area = this.sideLength * this.anotherSideLength

}
```

What if we also want to represent squares, that is, rectangles with four sides of equal length? We’d like to be able to write `new Square(10)` and the like.

Of course, we might simply extend `Shape` in a `Square` class:

```class Square(val sideLength: Double) extends Shape {

def area = this.sideLength * this.sideLength

}
```

The bothersome thing about this solution is that the code is quite redundant: the algorithm for computing the area of a square is the same as that for a rectangle; it just happens that the sides are equal in length. This approach isn’t up to par in terms of conceptual modeling, either: it makes squares a subtype of `Shape` alongside rectangles, whereas we humans prefer to think of a squares as a special case of a rectangle; each square is a square, a shape, and a rectangle.

The fix is simple: we can define squares as a subtype of rectangles, as shown in the diagram below. We can do this even though `Rectangle` is a regular class, not a trait.

## Subclasses and Superclasses

Let’s define `Square` like this instead:

```class Square(size: Double) extends Rectangle(size, size) {

}
```
We again use the `extends` keyword, but this time we follow it with the name of a regular class rather than a trait. We say: the class `Square` inherits the class `Rectangle`. The inheriting class is known as a subclass (aliluokka); the class being inherited from is known as a superclass (yliluokka). `Square`s. This gives all `Square` objects the additional type of `Rectangle`.
`Square` has only one constructor parameter that determines the length of each side.
To create an instance of a subclass, any initialization steps that the superclass demands must also be performed (such as initializing the superclass’s instance variables). It’s common to pass constructor parameters from a subclass to the superclass, as shown here. In this example, we state that whenever a `Square` object is created, we initialize a `Rectangle` so that each of its two constructor parameters (each side length) gets the value of the new `Square`’s single constructor parameter. (See the animation below.)
We could have simply left out the empty curly brackets. (In this example, we haven’t given squares any methods or instance variables that rectangles don’t have.)

### Inheritance vs. traits

Extending a superclass with a subclass looks much like extending a trait with a class. The two techniques are closely related.

There are differences, though; let’s compare. First, consider traits and how the `Rectangle` class extends the `Shape` trait:

When using a trait Example
The supertype is represented by a trait. `trait Shape`
Each subtype extends (“mixes in”) that trait. `class Rectangle` `extends Shape`
A trait can define abstract methods and variables. `def area: Double`
A trait cannot be instantiated directly. One does not simply write `new Shape`.
A trait cannot take constructor parameters. `trait Shape(...)` is invalid.
A class (or trait) may directly extend multiple traits. `class X extends Trait1` `with Trait2 with Trait3` is fine.

And here is a similar table about inheritance and the example of `Rectangle` as a superclass for `Square`:

When inheriting from a regular class Example
The supertype is represented by a (super)class. `class Rectangle`
Each subtype extends (“inherits”) that superclass. `class Square` `extends Rectangle`
An ordinary class cannot define abstract methods or variables. (But you can. See below.) All the methods on `Rectangle` have a function body.
A superclass can be instantiated directly. `new Rectangle` works.
A superclass can take constructor parameters. `class Rectangle(val x: Int, val y: Int)` `extends Shape` is fine.
(In Scala and many other languages:) A class can have only one immediate superclass.
`class X extends` `Super1 with Super2` is invalid.
(But `class X extends Super1` `with Trait1 with Trait2`
is fine.)

There are many programs where it’s reasonable to use either of these techniques.

## Abstract Classes

The distinction between traits and class-based inheritance is further complicated by the fact that it’s possible to define so-called abstract classes. We’ll approach this concept through an example.

Let’s return briefly to the domain of phone bills, previously featured in Chapter 2.3. In that chapter, you used a given class `PhoneCall`, which represented aspects of phone calls that were relevant for billing purposes. Below is an implementation for such a class. (For simplicity, the version shown here doesn’t add a network surcharge like the earlier class did.)

```class PhoneCall(initialFee: Double, pricePerMinute: Double, val duration: Double) {
def totalPrice = this.initialFee + this.pricePerMinute * this.duration
}
```

Suppose we now want to add text messages to phone bills. Moreover, we’d like to record, for each billable call and message, whether or not its price already includes a 24-percent value-added tax (VAT). Finally, we’d like to have a method for computing the tax-free price.

In other words, we’d like phone bills to list “billable transactions” that can be either phone calls or text messages. Here’s a first draft:

```class Transaction(val vatAdded: Boolean) {
def priceWithoutTax = if (this.vatAdded) this.totalPrice / 1.24 else this.totalPrice
}
```
```class PhoneCall(val duration: Double,
val initialFee: Double,
val pricePerMinute: Double,
def totalPrice = this.initialFee + this.pricePerMinute * this.duration
}
```
```class TextMessage(val price: Double, vatAdded: Boolean) extends Transaction(vatAdded) {
def totalPrice = this.price
}
```
We’d like to pass in a constructor parameter `vatAdded` to each `Transaction` in order to indicate whether the given prices include a 24% VAT. If the tax is included, `priceWithoutTax` subtracts the amount of tax in order to return the tax-free price.
The subclasses `PhoneCall` and `TextMessage` each take multiple constructor parameters. Most of these parameters are associated with these specific subclasses, but ...
... the value of `vatAdded` gets passed on as a constructor parameter to the superclass. The processing of that information is left entirely to `Transaction`.
This example code has a small but critical problem, however. The `priceWithoutTax` method calls `totalPrice` on a transaction object, but the program doesn’t ensure that all possible transaction objects actually have this method. (It so happens that each of the two subclasses that we’ve defined here do have the method, but more generally, it’s not clear that any instance of any subclass of `Transaction` will have it.) The compiler rejects this code.

What we need is a `totalPrice` method that is common to all possible objects of type `Transaction` but that is implemented in different ways by different subclasses. Something like this:

```class Transaction(val vatAdded: Boolean) {

def totalPrice: Double

def priceWithoutTax = if (this.vatAdded) this.totalPrice / 1.24 else this.totalPrice

}
```

In this version, the `totalPrice` method is abstract, with no implementation. It exists in order to guarantee that such a method is somehow implemented on all transaction objects, which makes it possible to implement `priceWithoutTax` in general terms within the `Transaction` superclass.

But ordinary classes weren’t supposed to have abstract methods, right!?

Indeed, the above second draft of `Transaction` doesn’t make it past the compiler, either. But this one does:

```abstract class Transaction(val vatAdded: Boolean) {

def totalPrice: Double

def priceWithoutTax = if (this.vatAdded) this.totalPrice / 1.24 else this.totalPrice

}
```
If you want abstract methods on a `class`, you can add `abstract` to the class definition.

Such a class is called an abstract class. A class that is not abstract may be referred to as a concrete class.

An abstract class is similar to a trait. Let’s include it in our comparison:

Trait Abstract superclass Concrete superclass
Can it have abstract methods? Yes. Yes. No.
Can it be directly instantiated using `new`? No. No. Yes.
Can it take constructor parameters? No. Yes. Yes.
Can a class extend several of them
(using `extends` and `with`)?
Yes. No. No.

An alternative implementation for `TextMessage`

Above, we implemented text messages like this:

```class TextMessage(val price: Double, vatAdded: Boolean) extends Transaction(vatAdded) {
def totalPrice = this.price
}
```

Perhaps you feel it’s redundant to use two names, `price` and `totalPrice`, that give you access to the same information. And it is unnecessary. This works, too:

```class TextMessage(val totalPrice: Double, vatAdded: Boolean) extends Transaction(vatAdded)
```

Simple as that. The only new thing about this is that the subclass turns `totalPrice` into a variable; there’s no `def` that implements the superclass method. But there’s nothing wrong with that; this is a valid way to implement a parameterless abstract method. The important thing is that an expression such as `myTextMessage.totalPrice` must have a `Double` value, one way or another. For a user of the text-message class, it’s generally irrelevant whether they are dealing with a `val` or an effect-free, parameterless method that efficiently returns the same value every time. (Further reading: the Wikipedia article on the uniform access principle.)

Couldn’t we have used a trait there?

As an alternative to the approach we adopted above, we could have made `Transaction` a trait, replacing `class` with `trait` in its definition. However, that solution is unsatisfactory in one respect: Scala prohibits traits from having constructor parameters, so we would have needed to make other changes to work around that.

Optional assignment: Rewrite (mentally, at least) `Transaction` and its subclasses. Use a trait instead of an abstract superclass.

Generally speaking, should I use a trait or a superclass?

Rule of thumb: Unless you have a specific reason to use an abstract class, use a trait instead, since traits are more flexibly extendable.

The convenience of constructor parameters might be a reason to use a superclass rather than a trait.

It can be tricky to choose among a trait, an abstract superclass, or a concrete superclass. However, in O1, such decisions are generally made for you and provided in the assignment specifications. You can worry about learning to make these decisions yourself later, in Programming Studio 2, for example. For more information, you can also take a look at Section 12.7 of Programming in Scala (Third Edition), one of the book recommendations on our Books and Other Resources page.

## Class Hierarchies and the Scala API

Chapter 7.2 demonstrated that we can represent conceptual hierarchies with traits. Inheritance is likewise useful in forming such hierarchies. Even though a class can have only one immediate superclass, it can have multiple indirect superclasses. In the diagram above, for instance, the immediate superclass of `Spider` is `Arthropod`, but `Animal` is also one of its superclasses.

Scala API’s ready-made classes also form hierarchies. Let’s consider a few examples.

### A hierarchy of GUI elements

The package `scala.swing` provides a selection of classes that represent GUI elements, building blocks for graphical user interfaces. The diagram below depicts a part of this hierarchy.

Chapter 12.3 contains an introduction to the GUI library known as Swing. That optional chapter is at the rear end of O1 and this ebook, but if you’re itching to read more about GUIs, go ahead and read it. Now that you’ve been introduced to inheritance, you should have the sufficient prerequisite knowledge for the chapter.

### The `Option` hierarchy (and sealed superclasses)

There’s a small class hierarchy associated with the `Option` type, too.

Since Chapter 4.3, you’ve known that there are two kinds of `Option` objects. Any object of type `Option` is either a `Some` object that contains a value or `None`. This is actually an example of inheritance: `Option` is an abstract class that the concrete class `Some` and the singleton object `None` extend.

Chapter 7.2 mentioned how to seal a trait: the `sealed` keyword makes it impossible to directly extend a trait except within the file that defines the trait itself. A superclass can also be sealed, and `Option` is just such a sealed class.

As we noted in Chapter 4.3, an `Option` can be either a `Some` or `None` (which are defined in the same file) but it can never, ever be anything else. Which is exactly what you want when you use `Option`. You can’t extend `Option` with a class of your own, and that’s good.

### The mother of all classes: `Any`

Let’s examine some objects in the Scala REPL:

```val miscellany = Vector(123, "llama", true, Vector(123, 456), new Square(10))miscellany: Vector[Any] = Vector(123, llama, true, Vector(123, 456), o1.shapes.Square@114c3c7)
```
We create a vector that contains some completely disparate objects: an `Int`, a `String`, a `Boolean`, a `Vector` of `Int`, and a `Square`.
Scala infers that the type of the vector’s elements is `Any`. That is, what we have is a “vector of any sorts of objects”. This suggests that integers, vectors, squares, and what have you, are all of type `Any`.

All Scala classes and singleton objects — including those you write — automatically inherit from a class called `Any`, even though we don’t usually record this inheritance explicitly in code. All the objects in a Scala program always have the `Any` type in addition to any other types they may have.

It’s possible to use this top-level class as a type for a variable, as illustrated below.

```var someObject: Any = "kumquat"someObject: Any = kumquat
someObject.isInstanceOf[Any]res0: Boolean = true
someObject.isInstanceOf[String]res1: Boolean = true
someObject.isInstanceOf[Square]res2: Boolean = false
someObject = new Square(10)someObject: Any = o1.shapes.Square@ecfb83
someObject.isInstanceOf[Any]res3: Boolean = true
someObject.isInstanceOf[String]res4: Boolean = false
someObject.area<console>:12: error: value area is not a member of Any
someObject.area
^
```
As the name suggests, you can use a variable of type `Any` to refer to any object. The object can be a string or a square, for instance.
So, the static type of `someObject` is `Any`, and the expression `someObject.isInstanceOf` is valid because (and only because) the `isInstanceOf` method is defined in the `Any` class and is therefore available on any Scala object.
The attempted method call `someObject.area` fails even though the variable happens to store a `Square` object which has an `area` method. The variable’s static type limits what you can do with it.

In most cases, it’s not sensible to use variables of type `Any`, since the type’s genericity so constricts what you can do with such variables. With `Any` as the static type, you can use the variable only for the operations that are defined on `Any`; those extremely generic methods that are common to all Scala objects include `isInstanceOf`, `toString`, `==`, `!=`, and a handful of others. Generally, it makes sense to use variables with more specific types, which is of course what we’ve been doing already. (See the optional material below for a further discussion.)

### Something you may have noticed in the docs

The Scaladoc pages for many classes say `extends AnyRef` near the top. Here’s a familiar example:

But we haven’t seen `extends AnyRef` in the Scala code; why is it there in the docs? And why `AnyRef`, not `Any`?

### The mother of most classes: `AnyRef` a.k.a. `Object`

Scala’s root type `Any` divides in two “branches”. It has two immediate subclasses, `AnyVal` and `AnyRef`:

This division to `AnyRef` and `AnyVal` has to do with the way the Scala language is implemented and isn’t too significant to the Scala beginner or for learning the basics of programming more generally. Nevertheless, it’s good to be aware that these types exist so you know why they sometimes crop up in Scaladocs, REPL outputs, and error messages.

`AnyVal` is a superclass for some API classes that define certain data types that are simple but operate more efficiently than other classes do. The familiar data types `Int`, `Double`, `Boolean`, `Char`, and `Unit` descend from `AnyVal`, as do a few others. It’s relatively uncommon to extend `AnyVal` in an application; in O1, we don’t do that at all.

`AnyRef`, on the other hand, is a superclass for all other classes and singleton objects. The classes `String` and `Vector`, for instance, derive from `AnyRef`, as does the `Transaction` class we just wrote.

When using the common JVM-based implementation of Scala (as we do; Chapter 5.4), `AnyRef` is sometimes (and somewhat confusingly) also known by the name `Object` for JVM-specific technical reasons.

We can spot `AnyVal` and `AnyRef` a.k.a. `Object` in the REPL, too:

```val miscellany2 = Vector(123, true)miscellany2: Vector[AnyVal] = Vector(123, true)
val miscellany3 = Vector("llama", Vector(123, 456), new Square(10))miscellany3: Vector[Object] = Vector(llama, Vector(123, 456), o1.shapes.Square@667113)
```
`Int` and `Boolean` descend from `AnyVal`.
`String`, `Vector`, and `Square` descend from `Object`, which is effectively synonymous with `AnyRef`.

## Overriding Supertype Methods

Since Week 2, we have used `override` for replacing default method implementations with class-specific ones. In particular, we have used this keyword in:

• `toString` methods (Chapter 2.5): the methods that we’ve
written have overridden the default implementation (which produces descriptions such as `o1.shapes.Square@ecfb83`). That default implementation comes from class `AnyRef`.
• the event handlers on `View`s (such as `onClick`; Chapter 3.1): the default implementations in class `View` react to events by doing nothing at all but you can override them with whichever behavior you wish your application to have.

You can also override other methods in type hierarchies. As an experiment, let’s write a few mini-classes.

```class A {
def test() = {
println("Greetings from class A.")
}
}
```
```class B extends A {
}
```
```class C extends A {
override def test() = {
println("Greetings from class C.")
}
}
```
```class D extends C {
}
```
```class E extends D {
override def test() = {
println("Greetings from class E.")
}
}
```

Now let’s use our classes in the REPL:

```(new A).test()Greetings from class A.
(new B).test()Greetings from class A.
(new C).test()Greetings from class C.
(new D).test()Greetings from class C.
(new E).test()Greetings from class E.
```
Class `B` doesn’t define an overriding implementation, so a `B` object simply inherits the `test` implementation of `A`.
Class `C` overrides `test`.
Class `D` doesn’t override the method. A `D` object uses the implementation from its immediate superclass `C` (which overrides the one from `A`).
Class `E` does supply an overriding implementation that supersedes both the one in `C` and the one in `A`.

Let’s explore further:

```var myObject = new AmyObject: A = A@e1ee21
myObject.test()Greetings from class A.
myObject = new CmyObject: A = C@c081a6
myObject.test()Greetings from class C.
```
The variable’s static type is `A`. Its value has the dynamic type `C`.
We can call `test` on any expression with the static type `A` (or one of `A`’s subtypes); that is, we can call it on any object that is guaranteed to have the method. On the other hand, what happens when we do so depends on the dynamic type of the object that receives the message. Here, we execute the `test` implementation defined on `C` objects, even though the variable is of type `A`.

One more class:

```class F extends E {
override def test() = {
super.test()
println("Greetings from class F.")
}
}
```
You can use the `super` keyword to refer to an implementation defined in a supertype. Here, we first call the superclass’s version of `test`. As a consequence, the `test` method of an `F` object first does whatever the `test` method on its superclass `E` does and then produces a printout specific to `F`. See below for an example.
```(new F).test()Greetings from class E.
Greetings from class F.
```

In Scala, you must always explicitly use the `override` keyword whenever you wish to override a method.

Why require an explicit `override`? Because it is “salty”.

By writing `override` in your program, you acknowledge that you are deliberately superseding a method implementation defined on a supertype. If the keyword was optional, you might very easily give your method a name that is already used in a supertype. Such a thing could happen quite accidentally and unknowingly, possibly spawning exotic bugs.

Like static typing, this requirement is a language feature that reduces the chance of human error. Such a language feature, which makes it harder to write bad code, is sometimes called “syntactic salt” (cf. the more common term syntactic sugar).

As an added benefit, the keyword makes overriding explicit to the program’s readers.

### Practice on inheritance and overriding

The frivolous program below features a combination of many of the techniques that we just discussed. You can use it for checking your understanding. If you can tell — in detail! — what this program does, then you will have grasped some of the main principles of inheritance.

Read the code below. Painstakingly consider which exact lines of text it outputs and in which order. Ideally, you should write down what you think the program outputs.

```object Cruising extends App {
val car = new Car
car.start()
}
```
```class Car {
private val passengers = Buffer[Passenger]()

passenger.sitDown()
this.passengers += passenger
}

def start() = {
println("(The car won't start.)")
for (passenger <- this.passengers) {
passenger.remark()
}
}
}
```
```abstract class Passenger(val name: String) {
def sitDown() = {
println(this.name + " finds a seat.")
}

def speak(sentence: String) = {
println(this.name + ": " + sentence)
}

def diagnosis: String

def remark() = {
this.speak(this.diagnosis)
}
}
```
```abstract class Student(name: String) extends Passenger(name) {
def diagnosis = "No clue what's wrong."
}
```
```class Schoolkid(name: String) extends Student(name)
```
```abstract class TechStudent(name: String) extends Student(name) {
override def remark() = {
super.remark()
this.speak("Clear as day.")
}
}
```
```class ChemicalEngineer extends TechStudent("C. Chemist") {
override def diagnosis = "It's the wrong octane. Next time, I'll do the refueling."
}
```
```class MechanicalEngineer extends TechStudent("M. Machine") {

override def diagnosis = "Nothing wrong with the gas. It must be the pistons."

override def speak(sentence: String) = {
super.speak(sentence.replace(".", "!"))
}
}
```
```class ElectricalEngineer extends TechStudent("E. Electra") {
override def sitDown() = {
println(this.name + " claims a front seat.")
}

override def diagnosis = "Hogwash. The spark plugs are faulty."
}
```
```class ComputerScientist extends TechStudent("C.S. Student") {
override def remark() = {
this.speak("No clue what's wrong.")
this.speak(this.diagnosis)
}

override def diagnosis = "Let's all get out of the car, close the doors, reopen, and try again."
}
```

Did you read the program carefully? Did you write down the output you expect?

Now open the Subtypes module and run `o1.cruising.Cruising` (which is the above program). Was the output precisely what you expected? If not, find out why.

You may wish to use the debugger as an aid.

## Assignment: Items within Items

### Introduction

Imagine we’re working on an application that needs to represent items of various sorts. We have a simple class `Item`:

```class Item(val name: String) {
override def toString = this.name
}
```

For this small programming assigment, let’s adopt the following goal: we wish our program to have not only “simple items”, as defined above, but also items that can contain other items. For instance, we might have a bag that contains a book and a box, and the box might further contain a ring.

Write a subclass for `Item`. Name it `Container`. This subclass will represent items that can contain other items, such as bags and boxes:

• Containers each have a name, just like other items do.
• They have an `addContent` method, which places an item within the container.
• And a `contents` method that returns the previously added items in a `Vector`.
• Their `toString` implementation differs from that of other items.

Your class should work as shown below.

```val container1 = new Container("box")container1: o1.items.Container = box containing 0 item(s)
container1res5: o1.items.Container = box containing 1 item(s)
val container2 = new Container("bag")container2: o1.items.Container = bag containing 0 item(s)
container2res6: o1.items.Container = bag containing 2 item(s)
container1.contentsres7: Vector[o1.items.Item] = Vector(ring)
container2.contentsres8: Vector[o1.items.Item] = Vector(book, box containing 1 item(s))
```

The `toString` method’s return value should count only the container’s immediate contents. For instance, in the REPL session above, the bag is shown as containing only two items, even though the box in the bag further contains the ring.

(How could we count all the “contents of the contents”, too? You’ll see in Chapter 12.1.)

### Instructions and hints

• There is some starter code in `o1.items` within the Subtypes module.
• Don’t forget to pass a constructor parameter to the superclass `Item`.
• Don’t use `val` to (re)define the instance variable `name` within the `Container` subclass. That variable is already defined in the superclass. It’s perfectly fine to give `Container`’s constructor parameter the name `name`, though.
• Note that what you `override` in this assignment isn’t the generic `toString` from `AnyRef`, as in many other programs, but the `toString` implementation in `Item`.
• Can you implement the `toString` in `Container` so that you use the superclass’s implementation rather than directly accessing the container’s name? (This is optional.)
• Do not add any public members in the class beyond what was requested. Private members you are free to add as you see fit.

A+ presents the exercise submission form here.

## Tailoring Instances of a Supertype

In Chapter 2.4, you learned to create an object that has an instance-specific method in addition to the methods defined in a class:

```val superman = new Person("Clark") {
def fly = "WOOSH!"
}superman: Person{def fly: String} = \$anon\$1@25ba32e0
```

Since then, we’ve used this technique when creating instances of the `View` class: we have given each of our `View` objects a set of tailor-made methods that suits the application.

Tailoring instances in this way is actually a form of inheritance. For example, what the above command actually does is define a nameless subclass of `Person` “on the fly” and immediately create a single instance of that subclass. Along the same lines, we have written diverse implementations for the abstract `makePic` method of the superclass `View`.

The same works in general for traits and superclasses. Read on if you wish.

Defining a subtype “on the fly”

You can also extend a trait “on the fly” as you create an object.

To set up the next example, let’s define a couple of traits and one concrete class. These three types are entirely distinct from each other.

```class Animal(val species: String) {
override def toString = "an animal, more specifically a " + this.species
}
trait Spitting {
def spit = "ptui!"
}
trait Humped {
def numberOfHumps: Int
}defined class Animal
defined trait Spitting
defined trait Humped
```

Let’s now define a new subclass of `Animal` that has no name and that has the trait `Spitting`. While we’re at it, let’s instantiate that class immediately. The result is an object of the combined type `Animal with Spitting`, which we’ve defined on the fly:

```val pet = new Animal("llama") with Spittingpet: Animal with Spitting = an animal, more specifically a llama
```

This object has all the properties of `Animal`s as well as all the properties defined in the `Spitting` trait:

```pet.speciesres9: String = llama
pet.spitres10: String = ptui!
```

Of course, we could have also defined a named class, as shown below, and instantiated it as per usual.

```class Llama extends Animal("llama") with Spittingdefined class Llama
```

Adding methods on a type defined “on the fly”

Let’s continue our toy example. We’ll create an object of a type that:

• is a subclass of `Animal`;
• additionally extends the traits `Humped` and `Spitting`; and
• implements the abstract method `numberOfHumps` in the `Humped` trait in a specific way.
```val shipOfTheDesert = new Animal("dromedary") with Humped with Spitting {
def numberOfHumps = 1
}shipOfTheDesert: Animal with Humped with Spitting = an animal, more specifically a dromedary
```

Finally, let’s create an object of a nameless class that has the `Spitting` trait and a couple of additional properties (a `name` variable and a particular implementation of `toString`):

```val fisherman = new Spitting {
val name = "Eemeli"
override def toString = this.name
}fisherman: Spitting{val name: String} = Eemeli
```

Here we followed `new` with the name of a trait rather than a concrete class. However, this command does not directly instantiate the trait (which isn’t possible; Chapter 7.2). Instead, it defines a new type that extends the trait and additionally has the properties listed inside the curly brackets. It is that new type that is then instantiated.

Terms for googling: scala trait mixin, scala anonymous subclass.

Choosing static types for variables

Rule of thumb: static types in general and the static types of parameters in particular should be as “wide” as possible. That is, where possible, we’d like our variables to have a superclass or a trait as their type rather than a more specific class. That way, our methods and classes will be more generally useful and easier to modify.

Compare:

```def doSomething(circle: Circle) = {
// ...
}
```

vs.

```def doSomething(shape: Shape) = {
// ...
}
```

The first definition is sensible in case `doSomething` should work only on circles (say, because it depends on being able to access the given object’s radius, which other shapes don’t have). Otherwise, the second definition is probably better, since it works on different shapes, including future subclasses of `Shape` that haven’t even been written yet.

You can’t always generalize; otherwise we’d just give everything the `Any` type. But do generalize when you can.

Between public and private: `protected`

A subclass’s instances also have the superclasses’ `private` variables as part of their state. Inherited methods commonly use those private variables. However, you can’t directly refer to a private member of a superclass from the subclass’s program code. The same goes for private members on traits.

However, Scala, like some other languages, features another access modifier, `protected`. This modifier allows precisely what we just said `private` disallows: a `protected` variable or method is accessible not only to the class or trait itself but also within the code of its subtypes. (But not just anywhere, like a public member is.) An internet search should bring up many examples.

Multiple inheritance

As noted above, a class can extend only a single superclass directly. Why?

Search online for multiple inheritance (moniperintä). You may also wish to look up the “deadly diamond of death” that is sometimes associated with multiple inheritance and that is held to be a serious problem by some but not all programmers.

And here is some slightly provocative but interesting reading (mostly to those students who already know something about Java and its interface construct):'Interface' Considered Harmful.

If you extend multiple traits, which method implementations do you get?

Here’s a simple example:

```trait X {
def method: String
}
trait A extends X {
override def method = "a's method"
}
trait B extends X {
override def method = "b's method"
}defined trait X
defined trait A
defined trait B
class AB extends A with B
class BA extends B with Adefined class AB
defined class BA
(new AB).methodres11: String = b's method
(new BA).methodres12: String = a's method
```

The Liskov substitution principle

“Square as a subclass of rectangle” is a classic example when discussing the Liskov substitution principle, which we’ll only paraphrase here. This well-known design guideline is often held up as a criterion of object-oriented program quality.

For a class S to follow this principle, the following must be true:

If S is a subclass of T, all operations that are available and meaningful on instances of T are equally available and meaningful on instances of S.

In other words: where you have an instance of T, you can also use an instance of S.

Let’s return to the shape example and these two classes that we defined earlier:

```class Rectangle(val sideLength: Double, val anotherSideLength: Double) extends Shape {
def area = this.sideLength * this.anotherSideLength
}
```
```class Square(size: Double) extends Rectangle(size, size)
```

Does this code follow the Liskov substitution principle? What if we used `var` instead of `val` in class `Rectangle`? Recall: our goal when writing `Square` was to model the fact that a square is a rectangle whose sides are equal in length.

More in Wikipedia:

On dependencies between classes/traits

The chapter on traits (7.2) already brought up the notion that there is an asymmetric relationship between a subtype and a supertype: we define each subtype in terms of its supertype(s), not the other way around. This applies to inheritance, too:

• In a subclass definition, we record the superclass that the subclass extends. Given that relationship, we can rely on the fact that the inherited methods from the superclass are available for us to use within the subclass. We can write things like `this.methodInSuperclass`. We may also use the `super` keyword to refer to the superclass definition.
• We do not record the inheritance relationship in the superclass, and the superclass’s code is independent of the subclasses in this respect. We can't call `this.methodInSubclass`; we can invoke methods on `this` only if they are common to all instances of the supertype. There is no `sub` keyword.

If superclasses were dependent on their subclasses, changing those subclasses would necessitate changes in the superclass. That would be quite vexing. For instance: It’s fairly common to extend a superclass defined in a library (e.g., `View`). There is no way that the library’s creator can know all the possible subclasses that may be created for their class or react to changes in those subclasses.

On the other hand, it’s great that we can add methods to a superclass and those methods will then be available in all extending classes. Often, this works fine, but sometimes, we run into a weakness in inheritance-based program design:

On fragile superclasses

The fragile base class problem refers to situations where it’s impossible to modify a superclass without knowing details about its subclasses.

As one example, consider adding a method to a superclass: what if the new method happens to have the same name as one or more of the methods in the subclasses? We have a serious problem.

In a language such as Scala, our program will break down with a compile-time error that complains about a missing `override` modifier. In languages that don’t have such a modifier or that make it optional, we may get surprising and erroneous runtime behavior instead.

O1’s follow-on courses will discuss object-oriented design more deeply. In the meantime, you may find the Wikipedia article on fragile base classes interesting; see also composition over inheritance.

Preventing overriding and inheritance: `final`

If you add the `final` modifier in front of a `def`, the method can’t be overridden: instances of all subtypes will inherit the method as is. An attempt to override it will bring a compile-time error.

In front of `class`, the same `final` keyword disallows inheritance from that class altogether. (Cf. `sealed`, which limits direct inheritance to within a single file.)

When used appropriately, the `final` modifier may make programs easier to comprehend and prevent inappropriate use of a class. Some programs’ efficiency is improved by `final`, since the compiler doesn’t need to worry about overriding. Many of the classes in the standard Scala API are `final` .

## Summary of Key Points

• Inheritance is an object-oriented technique in which subclasses extend a superclass. The subclasses, which represent more specific concepts, inherit the generic properties defined in the superclass.
• Traits and superclasses have much in common, but there are differences, too. Specifically:
• A class may have only one immediate superclass but it may extend multiple traits.
• Unlike a trait, a superclass may take constructor parameters.
• You can define a class as abstract, in which case it can contain abstract methods and variables just like a trait can. An abstract class can’t be instantiated directly but only via its subclasses.
• Classes and traits form hierarchies that represent hierarchies of concepts. In Scala, all classes are part of a hierarchy whose base is the API class `Any`.
• A subclass may override a superclass method with a subtype-specific implementation.
• Links to the glossary: inheritance, subclass, superclass, class hierarchy, `Any`; abstract class; static type, dynamic type; to override; sealed class; `final`.

## Feedback

Please note that this section must be completed individually. Even if you worked on this chapter with a pair, each of you should submit the form separately.

## Credits

Thousands of students have given feedback that has contributed to this ebook’s design. Thank you!

The ebook’s chapters, programming assignments, and weekly bulletins have been written in Finnish and translated into English by Juha Sorva.

The appendices (glossary, Scala reference, FAQ, etc.) are by Juha Sorva unless otherwise specified on the page.

The automatic assessment of the assignments has been developed by: (in alphabetical order) Riku Autio, Nikolas Drosdek, Joonatan Honkamaa, Jaakko Kantojärvi, Niklas Kröger, Teemu Lehtinen, Strasdosky Otewa, Timi Seppälä, Teemu Sirkiä, and Aleksi Vartiainen.

The illustrations at the top of each chapter, and the similar drawings elsewhere in the ebook, are the work of Christina Lassheikki.

The animations that detail the execution Scala programs have been designed by Juha Sorva and Teemu Sirkiä. Teemu Sirkiä and Riku Autio did the technical implementation, relying on Teemu’s Jsvee and Kelmu toolkits.

The other diagrams and interactive presentations in the ebook are by Juha Sorva.

The O1Library software has been developed by Aleksi Lukkarinen and Juha Sorva. Several of its key components are built upon Aleksi’s SMCL library.

The pedagogy of using O1Library for simple graphical programming (such as `Pic`) is inspired by the textbooks How to Design Programs by Flatt, Felleisen, Findler, and Krishnamurthi and Picturing Programs by Stephen Bloch.

The course platform A+ was originally created at Aalto’s LeTech research group as a student project. The open-source project is now shepherded by the Computer Science department’s edu-tech team and hosted by the department’s IT services. Markku Riekkinen is the current lead developer; dozens of Aalto students and others have also contributed.

The A+ Courses plugin, which supports A+ and O1 in IntelliJ IDEA, is another open-source project. It was created by Nikolai Denissov, Olli Kiljunen, Nikolas Drosdek, Styliani Tsovou, Jaakko Närhi, and Paweł Stróżański with input from Juha Sorva, Otto Seppälä, Arto Hellas, and others.

For O1’s current teaching staff, please see Chapter 1.1.