標籤:swift 屬性 方法 析構
一、 繼承
1. Swift中定義的類,如果不繼承自任何類,它就是基類。這一點和objective-c中定義的類不一樣,在objective-c中定義的類預設的基類是NSObject。
2. 重寫父類的方法及屬性,必須使用override的關鍵字(這樣處理的話,更清晰了,很容易看出是父類的方法還是自己類中的方法)。
3. 如果在類,方法,屬性 前面用final進行了修飾,就不允許被繼承或者被重寫。
類繼承關係Demo:
class Animal { var speed : Int = 1 func run() { println("Animal is running") }}class Dog: Animal { override var speed : Int { get { return super.speed } set { if newValue > 100 { super.speed = 100 } else { super.speed = newValue } } } override func run() { println("Dog is running") }}
二、 構造方法
在Swift中,儲存屬性在定義的時候必須要進行初始化工作,這一點我在Swift:物件導向(屬性)中有提到過。如果不進行初始化的話,我們也可以在構造方法中完成初始化工作。
Swift中構造方法的特點:
1. 方法名字叫做init。
2. 沒有func關鍵字。
3. 沒有返回值。
Demo:
class Person { var name: String var age: Int init(name: String , age: Int) { self.name = name self.age = age }}var p = Person(name: "Rose", age: 30)
在本例中,有兩個儲存屬性name和age,它們在定義的時候均沒有完成初始化工作,但我們可以在init(name: String, age: Int) 這個構造方法中完成它們的初始化工作。self.name 和 self.age 就是定義的兩個屬性,而 name 和 age 就是外界傳遞過來的變數值。
三、 指定構造方法(Designated) 和 便利構造方法(Convenience)
關於指定構造方法和便利構造方法的使用有很多規則。
1. 只有便利構造方法才能調用當前類的其他構造方法。
class Person { var name: String var age: Int init(name: String, age: Int) { self.name = name self.age = age } init(name: String) { self.init(name: name, age: 10) }}
在上例中,試圖在init(name: String) 這個構造方法中調用init(name: String, age: Int)這個構造方法,並且age的預設值是10。但是程式會直接報錯。
可以看出,錯誤資訊很明顯,提示你在init(name: String) 構造方法之前加上convenience, 使這個構造方法變成便利構造方法即可。
2. 只有指定構造方法才能調用父類的構造方法
class Person { var name: String var age: Int init(name: String, age: Int) { self.name = name self.age = age } convenience init(name: String) { self.init(name: name, age: 10) }}class Jack: Person { convenience init(name: String) { super.init(name: name, age: 20) }}
上例中,試圖在Jack這個子類的 convenience init(name: String) 這個便利構造方法中調用父類Person的指定構造方法init(name: String, age: Int)。但是程式會報錯。
所以,我們將Jack這個類中的convenience這個關鍵字去掉即可。讓子類的直接構造方法調用父類的直接構造方法。
3. 有參的指定構造方法會覆蓋調用預設的無參指定構造方法。
在Swift中定義的類中,都有一個預設的無參指定構造方法,只是沒有顯示出來。例如:
class Person {}
它其實有一個 init(){} 指定構造方法,這也是為什麼可以書寫下面的程式碼完成對象的初始化工作。
var p = Person()
但是,如果你在代碼中書寫了有參指定構造方法,那麼預設的無參指定構造方法將被覆蓋掉。例如:
class Person { var name: String var age: Int init(name: String, age: Int) { self.name = name self.age = age }}
此時你再調用
var p = Person()
這句代碼將直接報錯了。
但如果想不管調用無參構造方法還是有參構造方法都可以。那麼你將預設的指定都早方法寫出來即可。
class Person { var name: String var age: Int init() { self.name = "rose" self.age = 20 } init(name: String, age: Int) { self.name = name self.age = age }}
此時你調用如下代碼,是完全可以的。
var p = Person()var p2 = Person(name: "tick", age: 20)
4. 如果父類中存在有參的指定構造方法,子類的指定構造方法不會自動調用父類無參的指定構造方法。
class Person { var name: String var age: Int init(name: String, age: Int) { self.name = name self.age = age }}class Jack: Person { override init(name: String, age: Int) { super.init() }}
子類Jack的構造方法調用了父類的init預設無參的構造方法,將會直接報錯。
所以我們在子類的構造方法中可直接調用父類的有參構造方法即可,代碼如下:
super.init(name: name, age: age)
5. 常量屬性只能在定義它的類的構造方法中初始化,不能在子類中初始化。
class Person { var name: String var age: Int let gender: String init(name: String, age: Int, gender: String) { self.name = name self.age = age self.gender = gender }}class Jack: Person { override init(name: String, age: Int, gender: String) { self.age = 10 self.gender = "W" super.init(name: name, age: age, gender: gender) }}
注意到在Person中定義的gender是一個常量,所以我試圖在子類中對其進行初始化,是失敗的。錯誤資訊。
關於構造方法的知識,開起來似乎有點複雜,我們也可以分析下面兩站流程圖來分析上面我所提到的知識點。
四、 析構方法
Swift中的析構方法類似於objective-c中的dealloc的處理。
Demo:
class Dog { deinit { println("Dog Die") }}func oneDog() { var d = Dog()}println("New Dog")oneDog()println("Game Over")
oneDog函數執行完畢後,d變數被銷毀,Dog對象就失去了強引用,也就被銷毀了,會調用析構方法deinit
最終列印結果
"New Dog"
"Dog Die"
"Game Over"
註: 一個對象被釋放前,先自動調用自己的析構方法,然後一層一層往上調用父類的析構方法
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。
Swift:物件導向(繼承與構造方法)