Easy Tutorial
❮ Swift Subscripts Swift Extensions ❯

Swift Inheritance

Inheritance can be understood as a class acquiring the methods and properties of another class.

When a class inherits from another class, the inheriting class is called the subclass, and the class being inherited from is called the superclass (or parent class).

In Swift, a class can call and access the methods, properties, and subscript scripts of its superclass and can override them.

We can also add property observers to inherited properties in a class.


Base Class

A class that does not inherit from any other class is called a base class (Base Class).

In the following example, we define a base class StudDetails that describes a student (stname) and their scores in various subjects (mark1, mark2, mark3):

class StudDetails {
    var stname: String!
    var mark1: Int!
    var mark2: Int!
    var mark3: Int!
    init(stname: String, mark1: Int, mark2: Int, mark3: Int) {
        self.stname = stname
        self.mark1 = mark1
        self.mark2 = mark2
        self.mark3 = mark3
    }
}
let stname = "swift"
let mark1 = 98
let mark2 = 89
let mark3 = 76

let sds = StudDetails(stname:stname, mark1:mark1, mark2:mark2, mark3:mark3)

print(sds.stname)
print(sds.mark1)
print(sds.mark2)
print(sds.mark3)

The output of the above program is:

swift
98
89
76

Subclass

A subclass refers to a new class created based on an existing class.

To specify a superclass for a class, place the superclass name after the subclass name, separated by a colon (:), in the following syntax:

class SomeClass: SomeSuperclass {
    // Class definition
}

Example

In the following example, we define a superclass StudDetails and then create a subclass Tom that inherits from it:

class StudDetails {
    var mark1: Int
    var mark2: Int

    init(stm1: Int, results stm2: Int) {
        mark1 = stm1
        mark2 = stm2
    }

    func show() {
        print("Mark1:\(self.mark1), Mark2:\(self.mark2)")
    }
}

class Tom: StudDetails {
    init() {
        super.init(stm1: 93, results: 89)
    }
}

let tom = Tom()
tom.show()

The output of the above program is:

Mark1:93, Mark2:89

Overriding

A subclass can implement its own custom functionality by overriding inherited instance methods, class methods, instance properties, or subscript scripts. This behavior is called overriding.

We use the override keyword to implement overriding.

Accessing Superclass Methods, Properties, and Subscript Scripts

You can access the superclass methods, properties, or subscript scripts by using the super prefix.

Overriding Accessing Methods, Properties, Subscript Scripts
Method super.someMethod()
Property super.someProperty()
Subscript Script super[someIndex]

Overriding Methods and Properties

Overriding Methods

We can use the override keyword to override methods in our subclass.

In the following example, we override the show() method:

class SuperClass {
    func show() {
        print("This is the superclass SuperClass")
    }
}

class SubClass: SuperClass {
    override func show() {
        print("This is the subclass SubClass")
    }
}

let superClass = SuperClass()
superClass.show()

let subClass = SubClass()
subClass.show()

The output of the above program is:

This is the superclass SuperClass
This is the subclass SubClass

Overriding Properties

You can override properties in a subclass using the override keyword. You can provide custom getter (or setter) to override any inherited property, whether the inherited property is a stored property or a computed property.

The subclass does not know whether the inherited property is a stored property or a computed property; it only knows that the inherited property will have a name and a type. Therefore, when you override a property, you must specify both its name and type.

Important points:

The following example defines a superclass Circle and a subclass Rectangle. In the Rectangle class, we override the area property:

class Circle {
    var radius = 12.5
    var area: String {
        return "Rectangle radius \(radius) "
    }
}

// Inherit from superclass Circle
class Rectangle: Circle {
    var print = 7
    override var area: String {
        return super.area + " , but now overridden as \(print)"
    }
}

let rect = Rectangle()
rect.radius = 25.0
rect.print = 3
print("Radius \(rect.area)")

The output of the above program is:

Radius Rectangle radius 25.0  , but now overridden as 3

Overriding Property Observers

You can add property observers to an inherited property by overriding it. This way, you can monitor changes to the inherited property's value.

Note: You cannot add property observers to inherited constant stored properties or inherited read-only computed properties.

class Circle {
    var radius = 12.5
    var area: String {
        return "Rectangle radius is \(radius) "
    }
}

class Rectangle: Circle {
    var print = 7
    override var area: String {
        return super.area + " , but now overridden as \(print)"
    }
}

let rect = Rectangle()
rect.radius = 25.0
rect.print = 3
print("Radius: \(rect.area)")

class Square: Rectangle {
    override var radius: Double {
        didSet {
            print = Int(radius/5.0)+1
        }
    }
}

let sq = Square()
sq.radius = 100.0
print("Radius: \(sq.area)")

The output is:

Radius: Rectangle radius is 25.0  , but now overridden as 3
Radius: Rectangle radius is 100.0  , but now overridden as 21

Preventing Overrides

You can prevent them from being overridden by using the final keyword.

If you override a final method, property, or subscript, you will get a compile-time error.

You can mark the entire class as final by adding the final attribute before the class keyword (final class), making it non-inheritable, otherwise, you will get a compile-time error.

final class Circle {
    final var radius = 12.5
    var area: String {
        return "Rectangle radius is \(radius) "
    }
}
class Rectangle: Circle {
    var print = 7
    override var area: String {
        return super.area + " , but now overridden as \(print)"
    }
}

let rect = Rectangle()
rect.radius = 25.0
rect.print = 3
print("Radius: \(rect.area)")

class Square: Rectangle {
    override var radius: Double {
        didSet {
            print = Int(radius/5.0)+1
        }
    }
}

let sq = Square()
sq.radius = 100.0
print("Radius: \(sq.area)")

Due to the use of the final keyword in the examples above, which does not allow overriding, the execution will result in an error:

error: var overrides a 'final' var
    override var area: String {
                 ^
note: overridden declaration is here
    var area: String {
        ^
error: var overrides a 'final' var
    override var radius: Double {
                 ^
note: overridden declaration is here
    final var radius = 12.5
              ^
error: inheritance from a final class 'Circle'
class Rectangle: Circle {
      ^
❮ Swift Subscripts Swift Extensions ❯