English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Swift 継承

继承我们可以理解为一个类获取了另外一个类的方法和属性。

当一个类继承其它类时,继承类叫子类,被继承类叫超类(或父类)

在 Swift 中,类可以调用和访问超类的方法,属性和下标脚本,并且可以重写它们。

我们也可以为类中继承来的属性添加属性观察器。

基类

没有继承其它类的类,称之为基类(Base Class)。

以下示例中我们定义了基类 StudDetails ,描述了学生(stname)及其各科成绩的分数(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.mark)1)
print(sds.mark)2)
print(sds.mark)3)

以上程序执行输出结果为:

swift
98
89
76

子クラス

子クラスとは、既存のクラスの上に新しいクラスを作成することを指します。

あるクラスの超クラスを指明するには、超クラス名を子クラス名の後に書き、カラム(:)で区切ります。以下の形式で記述します。

class SomeClass: SomeSuperclass {
    // クラスの定義
}

オンラインサンプル

以下の例では、超クラス StudDetails を定義し、その後に子クラス 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()

以上程序执行输出结果为:

Mark1:93, Mark2:89

オーバーライド(Overriding)

子クラスは、継承した例のメソッド、クラスメソッド、例のプロパティ、またはインデックスシェイプを使用して、独自のカスタマイズ機能を実現できます。この行動をオーバーライド(overriding)と呼びます。

override キーワードを使用してオーバーライドを実現できます。

超クラスのメソッド、プロパティ及びインデックスシェイプにアクセス

superプレフィックスを使用して、超クラスのメソッド、プロパティ、インデックスシェイプにアクセスできます。

オーバーライド メソッド、プロパティ、インデックスシェイプにアクセス
メソッド super.somemethod()
プロパティ super.someProperty()
インデックスシェイプ super[someIndex]

メソッドとプロパティのオーバーライド

メソッドのオーバーライド

子クラスでは、override キーワードを使用して超クラスのメソッドをオーバーライドできます。

以下の例では、show() メソッドをオーバーライドしています:

class SuperClass {
    func show() {
        print("これは超クラス SuperClassです")
    }
}
class SubClass: SuperClass {
    override func show() {
        print("これは子クラス SubClassです")
    }
}
let superClass = SuperClass()
superClass.show()
let subClass = SubClass()
subClass.show()

以上程序执行输出结果为:

这是超类 SuperClass
这是子类 SubClass

重写属性

你可以提供定制的 getter(或 setter)来重写任意继承来的属性,无论继承来的属性是存储型的还是计算型的属性。

子类并不知道继承来的属性是存储型的还是计算型的,它只知道继承来的属性会有一个名字和类型。所以你在重写一个属性时,必需将它的名字和类型都写出来。

注意点:

  • 如果你在重写属性中提供了 setter,那么你也一定要提供 getter。

  • 如果你不想在重写版本中的 getter 里修改继承来的属性值,你可以直接通过super.someProperty来返回继承来的值,其中someProperty是你要重写的属性的名字。

以下示例我们定义了超类 Circle 及子类 Rectangle, 在 Rectangle 类中我们重写属性 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)")

以上程序执行输出结果为:

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

重写属性观察器

你可以在属性重写中为一个继承来的属性添加属性观察器。这样一来,当继承来的属性值发生改变时,你就会监测到。

注意:你不可以为继承来的常量存储型属性或继承来的只读计算型属性添加属性观察器。

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

防止重写

我们可以使用 final 关键字防止它们被重写。

如果你重写了final方法,属性或下标脚本,在编译时会报错。

你可以通过在关键字class前添加final特性(final class)来将整个类标记为 final 的,这样的类是不可被继承的,否则会报编译错误。

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)")

上記の例では、final キーワードを使用してオーバーライドが許可されていないため、実行するとエラーが発生します:

エラー: var は 'final' var をオーバーライドしています
    override var area: String {
                 ^
ノート: オーバーライド宣言はここにあります
    var area: String {
        ^
エラー: var は 'final' var をオーバーライドしています
    override var radius: Double {
                 ^
ノート: オーバーライド宣言はここにあります
    final var radius = 12.5
              ^
エラー: 最終クラス 'Circle' からの継承
class Rectangle: Circle {
      ^