Menu
Coddy logo textTech

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 false

The 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
30

Each 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 seats
challenge icon

Challenge

Easy

Product 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())
}
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Object Oriented Programming

Practice on your own: Swift playground