Swift 繼承
繼承我們可以理解為一個(gè)類獲取了另外一個(gè)類的方法和屬性。
當(dāng)一個(gè)類繼承其它類時(shí),繼承類叫子類,被繼承類叫超類(或父類)
在 Swift 中,類可以調(diào)用和訪問超類的方法,屬性和下標(biāo)腳本,并且可以重寫它們。
我們也可以為類中繼承來的屬性添加屬性觀察器。
基類
沒有繼承其它類的類,稱之為基類(Base Class)。
以下實(shí)例中我們定義了基類 StudDetails ,描述了學(xué)生(stname)及其各科成績的分?jǐn)?shù)(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)
以上程序執(zhí)行輸出結(jié)果為:
swift 98 89 76
swift 98 89 76
子類
子類指的是在一個(gè)已有類的基礎(chǔ)上創(chuàng)建一個(gè)新的類。
為了指明某個(gè)類的超類,將超類名寫在子類名的后面,用冒號(:)分隔,語法格式如下
class SomeClass: SomeSuperclass { // 類的定義 }
實(shí)例
以下實(shí)例中我們定義了超類 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()
以上程序執(zhí)行輸出結(jié)果為:
Mark1:93, Mark2:89
重寫(Overriding)
子類可以通過繼承來的實(shí)例方法,類方法,實(shí)例屬性,或下標(biāo)腳本來實(shí)現(xiàn)自己的定制功能,我們把這種行為叫重寫(overriding)。
我們可以使用 override 關(guān)鍵字來實(shí)現(xiàn)重寫。
訪問超類的方法、屬性及下標(biāo)腳本
你可以通過使用super前綴來訪問超類的方法,屬性或下標(biāo)腳本。
重寫 | 訪問方法,屬性,下標(biāo)腳本 |
---|---|
方法 | super.somemethod() |
屬性 | super.someProperty() |
下標(biāo)腳本 | super[someIndex] |
重寫方法和屬性
重寫方法
在我們的子類中我們可以使用 override 關(guān)鍵字來重寫超類的方法。
以下實(shí)例中我們重寫了 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()
以上程序執(zhí)行輸出結(jié)果為:
這是超類 SuperClass 這是子類 SubClass
重寫屬性
你可以提供定制的 getter(或 setter)來重寫任意繼承來的屬性,無論繼承來的屬性是存儲型的還是計(jì)算型的屬性。
子類并不知道繼承來的屬性是存儲型的還是計(jì)算型的,它只知道繼承來的屬性會有一個(gè)名字和類型。所以你在重寫一個(gè)屬性時(shí),必需將它的名字和類型都寫出來。
注意點(diǎn):
如果你在重寫屬性中提供了 setter,那么你也一定要提供 getter。
如果你不想在重寫版本中的 getter 里修改繼承來的屬性值,你可以直接通過super.someProperty來返回繼承來的值,其中someProperty是你要重寫的屬性的名字。
以下實(shí)例我們定義了超類 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 + " ,但現(xiàn)在被重寫為 \(print)" } } let rect = Rectangle() rect.radius = 25.0 rect.print = 3 print("Radius \(rect.area)")
以上程序執(zhí)行輸出結(jié)果為:
Radius 矩形半徑 25.0 ,但現(xiàn)在被重寫為 3
重寫屬性觀察器
你可以在屬性重寫中為一個(gè)繼承來的屬性添加屬性觀察器。這樣一來,當(dāng)繼承來的屬性值發(fā)生改變時(shí),你就會監(jiān)測到。
注意:你不可以為繼承來的常量存儲型屬性或繼承來的只讀計(jì)算型屬性添加屬性觀察器。
class Circle { var radius = 12.5 var area: String { return "矩形半徑為 \(radius) " } } class Rectangle: Circle { var print = 7 override var area: String { return super.area + " ,但現(xiàn)在被重寫為 \(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 ,但現(xiàn)在被重寫為 3 半徑: 矩形半徑為 100.0 ,但現(xiàn)在被重寫為 21
防止重寫
我們可以使用 final 關(guān)鍵字防止它們被重寫。
如果你重寫了final方法,屬性或下標(biāo)腳本,在編譯時(shí)會報(bào)錯(cuò)。
你可以通過在關(guān)鍵字class前添加final特性(final class)來將整個(gè)類標(biāo)記為 final 的,這樣的類是不可被繼承的,否則會報(bào)編譯錯(cuò)誤。
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 + " ,但現(xiàn)在被重寫為 \(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)")
由于以上實(shí)例使用了 final 關(guān)鍵字不允許重寫,所以執(zhí)行會報(bào)錯(cuò):
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 { ^
更多建議: