Swift Inheritance
Class inheritance lets one class build on another's properties and behavior, overriding what needs to change while reusing the rest through super.
Class Inheritance
A class can inherit from exactly one other class, becoming a subclass of that superclass. The subclass automatically gains all of the superclass's properties and methods, and can add new ones or override existing ones to change their behavior.
Overriding Methods and Properties
To change how an inherited method or computed property behaves, mark the new implementation with the override keyword. Swift checks at compile time that an overridden member really does exist on the superclass, which prevents typos from silently creating a brand-new method instead of replacing the intended one.
- Only classes support inheritance in Swift; structs and enums cannot inherit.
- The override keyword is required and is checked by the compiler against the superclass.
- Call super.methodName() inside an override to reuse the superclass's implementation instead of replacing it entirely.
- Mark a class or member final to forbid further overriding or subclassing.
- A subclass's designated initializer must call a superclass designated initializer, typically via super.init, before it can use self.
Overriding a method
class Vehicle {
let make: String
var speed = 0.0
init(make: String) {
self.make = make
}
func describe() -> String {
"\(make) traveling at \(speed) km/h"
}
}
class Car: Vehicle {
var numberOfDoors: Int
init(make: String, numberOfDoors: Int) {
self.numberOfDoors = numberOfDoors
super.init(make: make)
}
override func describe() -> String {
super.describe() + " with \(numberOfDoors) doors"
}
}
let car = Car(make: "Toyota", numberOfDoors: 4)
car.speed = 80
print(car.describe()) // Toyota traveling at 80.0 km/h with 4 doorsUsing super and a convenience initializer
class Animal {
let name: String
init(name: String) {
self.name = name
}
convenience init() {
self.init(name: "Unnamed Animal")
}
func makeSound() -> String {
"..."
}
}
class Dog: Animal {
override func makeSound() -> String {
"\(name) says Woof!"
}
}
let generic = Animal()
let rex = Dog(name: "Rex")
print(generic.makeSound()) // ...
print(rex.makeSound()) // Rex says Woof!Initializer Inheritance
Swift distinguishes designated initializers, which fully set up a class's own properties and then hand off to the superclass, from convenience initializers, which call another initializer in the same class. A required initializer forces every subclass to provide its own implementation, which is useful when a base class can't guess how subclasses should be constructed.
Designated, convenience, and required initializers
class Shape {
var name: String
required init(name: String) {
self.name = name
}
func area() -> Double {
0
}
}
class Polygon: Shape {
var sides: Int
required init(name: String) {
self.sides = 0
super.init(name: name)
}
convenience init(name: String, sides: Int) {
self.init(name: name)
self.sides = sides
}
}
final class Square: Polygon {
var length: Double = 0
convenience init(length: Double) {
self.init(name: "Square", sides: 4)
self.length = length
}
override func area() -> Double {
length * length
}
}
let square = Square(length: 5)
print("\(square.name): \(square.area())") // Square: 25.0Exercise: Swift Inheritance
How does a Swift class specify that it inherits from another class?