Initializers and super
Part of the Object Oriented Programming section of Coddy's Swift journey. Lesson 24 of 57.
When a subclass adds a stored property without a default, it needs its own initializer. It first sets its own properties and then calls the superclass initializer with super.init(...):
class Animal {
let name: String
init(name: String) { self.name = name }
}
class Bird: Animal {
let canFly: Bool
init(name: String, canFly: Bool) {
self.canFly = canFly
super.init(name: name)
}
}
let p = Bird(name: "Pip", canFly: false)
print("\(p.name) \(p.canFly)")Output:
Pip falseThe order matters: the subclass properties must have values before super.init runs, and inherited properties can only be used after it. Swift checks this at compile time:
init(name: String, canFly: Bool) {
// print(self.name) // error: self used before super.init
self.canFly = canFly // 1. own properties
super.init(name: name) // 2. superclass
print(self.name) // 3. now everything can be used
}Once a subclass defines its own initializer, it no longer inherits the superclass ones. A subclass can also override an initializer with the same parameters, marking it override init:
class Timer {
var seconds: Int
init(seconds: Int) { self.seconds = seconds }
}
class SafeTimer: Timer {
override init(seconds: Int) {
super.init(seconds: max(0, seconds))
}
}
print(SafeTimer(seconds: -5).seconds)
print(SafeTimer(seconds: 30).seconds)Output:
0
30Each level of a hierarchy initializes its own part and hands the rest to its superclass, so every property in the chain gets a value exactly once:
class Vehicle {
let wheels: Int
init(wheels: Int) { self.wheels = wheels }
}
class Car: Vehicle {
let seats: Int
init(seats: Int) {
self.seats = seats
super.init(wheels: 4)
}
}
class Taxi: Car {
let company: String
init(company: String) {
self.company = company
super.init(seats: 5)
}
}
let t = Taxi(company: "City Cabs")
print("\(t.company): \(t.wheels) wheels, \(t.seats) seats")Output:
City Cabs: 4 wheels, 5 seatsChallenge
EasyProduct stores name and price (in cents). Declare the subclass DiscountedProduct with a stored percent. Its initializer takes name, price and percent, stores percent, and calls super.init with the price already reduced by the percentage (rounded down). A percent outside 0-100 counts as 0. Add a method label() in DiscountedProduct that returns tea: 450 (10% off).
The supplied code reads lines name,price,percent, creates a DiscountedProduct for each and prints label().
Your code goes in Product.swift and DiscountedProduct.swift. main.swift holds the supplied input/output code and cannot be edited.
Try it yourself
// Supplied input/output code: keep it as it is
var input: [String] = []
while let line = readLine() { input.append(line) }
for line in input {
let p = line.split(separator: ",").map { String($0) }
let item = DiscountedProduct(name: p[0], price: Int(p[1])!, percent: Int(p[2])!)
print(item.label())
}
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Object Oriented Programming
1Classes and Objects
Working With FilesDefining ClassesMethods and selfInitializersClasses Are ReferencesRecap - Library Card4Encapsulation
Access ControlRead-Only From OutsideGuarding StateFailable InitializersRecap - Bank Account7Polymorphism and Generics
PolymorphismType CastingGeneric FunctionsGeneric TypesRecap - Shape Calculator5Inheritance
SubclassesOverriding MethodsInitializers and superfinal and HierarchiesRecap - Employee Hierarchy11Project: Library Management
Books and MembersBorrowing BooksPractice on your own: Swift playground