Introducing inheritance
In the previous chapter, you saw a pair of class examples: Person and Student.
class Person {
var firstName: String var lastName: String
init(firstName: String, lastName: String) { self.firstName = firstName
self.lastName = lastName
}
}
class Student {
var firstName: String var lastName: String var grades: [Grade] = []
init(firstName: String, lastName: String) { self.firstName = firstName
self.lastName = lastName
}
}
It’s not difficult to see that there’s an incredible amount of redundancy between
Person and Student. Maybe you’ve also noticed that a Student is a Person!
This simple case demonstrates the idea behind class inheritance. Much like in the real world, where you can think of a student as a person, you can represent the same relationship in code:
class Person {
var firstName: String var lastName: String
init(firstName: String, lastName: String) { self.firstName = firstName
self.lastName = lastName
}
}
class Student: Person { var grades: [Grade] = []
func recordGrade(_ grade: Grade) { grades.append(grade)
}
}
In this modified example, the Student class now inherits from Person, indicated by a colon after the naming of Student, followed by the class from which Student inherits, which in this case is Person.
Through inheritance, Student automatically gets the properties declared in the Person class, as well as the initializer and any methods defined within. In code, it would be accurate to say that a Student is a Person.
With drastically less code duplication, you can now create Student objects that have all the properties and methods of a Person:
let john = Person(firstName: "Johnny", lastName: "Appleseed") let jane = Student(firstName: "Jane", lastName: "Appleseed")
john.firstName // "John" jane.firstName // "Jane"
Additionally, only the Student object will have all of the properties and methods defined in the subclass:
let history = Grade(letter: "B", points: 9.0, credits: 3.0) jane.recordGrade(history)
// john.recordGrade(history) // john is not a student!
A class that inherits from another class is known as a subclass or a derived class, and the class from which it inherits as is known as a superclass or a base class.
The rules for subclassing are fairly simple:
- A Swift class can inherit from only one other class, a concept known as single inheritance.
- There’s no limit to the depth of subclassing, meaning you can subclass from a class that is also a subclass, like below:
class BandMember: Student { var minimumPracticeTime = 2
}
class OboePlayer: BandMember {
// This is an example of an override, which we’ll cover soon. override var minimumPracticeTime: Int {
get {
return super.minimumPracticeTime * 2
}
set {
super.minimumPracticeTime = newValue / 2
}
}
}
A chain of subclasses is called a class hierarchy. In this example, the hierarchy would be OboePlayer -> BandMember -> Student -> Person