Swift inherits

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

When a class inherits other classes, the inheritance class is called a child class, and the inherited class is called a super class (or parent class)

In Swift, classes can call and access super-class methods, properties, and underseed scripts, and can override them.

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


The base class

A class that does not inherit other classes, called Base Class.

In the following example, we define the base class StudDetails, which describes the scores of students (stname) and their grades in each section (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

print(stname)
print(mark1)
print(mark2)
print(mark3)

The output of the above program execution is:

swift
98
89
76
swift
98
89
76

Sub-class

A sub-class is a new class created on top of an existing class.

To indicate a class's super-class, write the super-class name after the sub-class name, separated by a colon (:), in the following syntax format

class SomeClass: SomeSuperclass {
    // 类的定义
}

Instance

In the following example we define the super-class StudDetails and then inherit it using the sub-class Tom:

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 execution is:

Mark1:93, Mark2:89

Rewriting (Overriding)

Sub-classes can implement their own customization through inherited instance methods, class methods, instance properties, or subsemase scripts, which we call overriding.

We can use the override keyword to implement the override keyword for override.

Access super-class methods, properties, and underseed scripts

You can access super-class methods, properties, or underseed scripts by using the super prefix.

Rewrite Access methods, properties, underseed scripts
Method super.somemethod()
Property super.someProperty()
The underlying script super[someIndex]

Override methods and properties

The override method

In our sub-classes we can use the override keyword to override methods to override super-classes.

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

class SuperClass {
    func show() {
        print("这是超类 SuperClass")
    }
}

class SubClass: SuperClass  {
    override func show() {
        print("这是子类 SubClass")
    }
}

let superClass = SuperClass()
superClass.show()

let subClass = SubClass()
subClass.show()

The output of the above program execution is:

这是超类 SuperClass
这是子类 SubClass

Override the property

You can provide a custom getter (or setter) to override any inherited property, whether the inherited property is stored or computational.

The sub-class does not know whether the inherited property is stored or computational, it only knows that the inherited property has a name and type. So when you override a property, you have to write its name and type.

Note points:

  • If you provide setter in the override property, then you must also provide getter.

  • If you don't want to modify the inherited property value in the getter in the rewrite version, you can return the inherited value directly through super.someProperty, where homeProperty is the name of the property you want to override.

The following examples define the hyper-class Circle and the sub-class Rectangle, in which we override the property area:

class Circle {
    var radius = 12.5
    var area: String {
        return "矩形半径 \(radius) "
    }
}

// 继承超类 Circle
class Rectangle: Circle {
    var print = 7
    override var area: String {
        return super.area + " ,但现在被重写为 \(print)"
    }
}

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

The output of the above program execution is:

Radius 矩形半径 25.0  ,但现在被重写为 3

Override the property observer

You can add a property observer to an inherited property in a property override. That way, when the inherited property value changes, you'll be able to monitor it.

Note: You can't add property observers to inherited constant storage properties or inherited read-only compute properties.

class Circle {
    var radius = 12.5
    var area: String {
        return "矩形半径为 \(radius) "
    }
}

class Rectangle: Circle {
    var print = 7
    override var area: String {
        return super.area + " ,但现在被重写为 \(print)"
    }
}


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

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


let sq = Square()
sq.radius = 100.0
print("半径: \(sq.area)")
半径: 矩形半径为 25.0  ,但现在被重写为 3
半径: 矩形半径为 100.0  ,但现在被重写为 21

Prevent overrides

We can use the final keyword to prevent them from being override.

If you rewrite the final method, property, or understag script, you will report an error at compile time.

You can mark the entire class as final by adding the final class before the keyword class, which is not inheritable, otherwise compilation errors will be reported.

final class Circle {
    final var radius = 12.5
    var area: String {
        return "矩形半径为 \(radius) "
    }
}
class Rectangle: Circle {
    var print = 7
    override var area: String {
        return super.area + " ,但现在被重写为 \(print)"
    }
}

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

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

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

Because the above instance uses the final keyword to not allow overrides, the execution will report 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 {
      ^