Swift Programming – Inheritance

In this tutorial you’ll learn about inheritance in Swift. To follow along, it is recommended to have a Mac and the Xcode IDE installed on it. This tutorial makes use of the Xcode playground for compilation of the Swift codes. If you do not have a Mac, you may try using the open-source code editors which support different operating systems such as AtomSublimeText or VSCode.

Inheritance

When you define a class, you can decide whether you will allow other classes to inherit from that class. A class which inherits from another, is known as a subclass. A class which allows inheritance, is known as a superclass. Inheritance allows a subclass to inherit its superclass‘ properties, methods and other characteristics.

Defining a Base Class

A base class is a class which does not inherit from another class. Let’s try an example of a base class in action.

class Smartphone {
    var sendSms = true
    var accessInternet = true
    var exchangeEmail = true
    var longBatteryLife = true
    var description: String {
        return "\(sendSms ? "can" : "cannot") send sms, \(accessInternet ? "has" : "has no") access to the internet, \(exchangeEmail ? "can" : "cannot") exchange email and \(longBatteryLife ? "has" : "does not have") a long battery life."
    }
    
    func playRingtone() {
        print("plays a default ringtone")
    }
}

let smartphone = Smartphone()
print("A smartphone \(smartphone.description)")

Subclassing

Subclassing is defining a new class with the intention of inheriting another class. Let’s see subclassing in action.

enum IPhoneModel: String {
    case se2ndGen = "iPhone SE (2nd generation)"
    case elevenPro = "iPhone 11 Pro"
    case elevenProMax = "iPhone 11 Pro Max"
    case eleven = "iPhone 11"
    case xs = "iPhone XS"
    case xsMax = "iPhone XS Max"
    case xr = "iPhone XR"
    case x = "iPhone X"
    case eight = "iPhone 8"
    case eightPlus = "iPhone 8 Plus"
    case seven = "iPhone 7"
    case sevenPlus = "iPhone 7 Plus"
    case sixS = "iPhone 6s"
    case sixSPlus = "iPhone 6s Plus"
    case six = "iPhone 6"
    case sixPlus = "iPhone 6 Plus"
    case se1stGen = "iPhone SE (1st generation)"
    case fiveS = "iPhone 5s"
}

class IPhone: Smartphone {
    var model: IPhoneModel = .fiveS
}

let iPhone = IPhone()
iPhone.model = IPhoneModel.x
print("\(iPhone.model.rawValue) \(iPhone.description)")

Overriding

In our base class SmartPhone, we have a method playRingtone(). Let’s say we want to output a different text in the console with our iPhone‘s instance. We can override the method playRingtone() in our subclass to do that.

class IPhone: Smartphone {
    var model: IPhoneModel = .fiveS
    
    override func playRingtone() {
        print("\(model.rawValue) plays the ringtone 'Let Me Love You (Marimba Remix)'.")
    }
}

iPhone.playRingtone()

Overriding Property Getters and Setters

Let’s say we want to add some specific texts alongside our inherited property variable description. You can get the inherited description‘s value by prepending super. to it.

class IPhone: Smartphone {
    var model: IPhoneModel = .fiveS
    override var description: String {
        return super.description + " This smartphone is \(model.rawValue)."
    }
    
    override func playRingtone() {
        print("\(model.rawValue) plays the ringtone 'Let Me Love You (Marimba Remix)'.")
    }
}

Preventing Overrides

Let’s say you are defining a new class and you do not want its property or method or subscript to be overridden in its subclasses. You can do so by writing the keyword final before their definitions, e.g. final var model: IPhoneModel = .fiveS. If you do not want a class to provide inheritance to other classes, you should write the keyword final before the class, e.g. final class IPhone: SmartPhone { }.

Reference

https://docs.swift.org/swift-book/LanguageGuide/Inheritance.html