標籤:swift ios 繼承 構造 析構
構造方法內容會多一些,涉及Swift中構造的一些規則與概念。這次寫了7個Person來複習,外加名人XiaoMing。
Mark:Playground真是個好東西,特別練習寫Swift時,即時顯示真是大讚!
一、繼承與重寫, 防止重寫
1.1 基類, 不繼承任何類. Swift不想OC或者Java中繼承自Object類.定義一個類,不繼承任何類,該類就是基類.
class Person1{ //這個Person1就是基類 func eat(){ println("eat a pig!") }}
1.2 繼承. Swift為單繼承
class XiaoMing1 : Person1{ var name = "xiaoming"}
1.3 重寫. 必須加關鍵字override. (OC,Java中是不必加的)
class XiaoHong1 : Person1{ override func eat() { super.eat(); //可以用super來調用父類中的屬性與方法 println("xiaohong eat a pig") }}var xh = XiaoHong1()xh.eat()
1.4 重寫屬性(儲存屬性與計算屬性)
可以用get/set/willSet/didSet進行屬性重寫
可以將一個唯讀屬性重寫為一個讀寫屬性,不可以將一個讀寫屬性重寫為一個唯讀屬性
也就是說: 重寫的範圍只能是 小-->大 (類似Java)
子類重寫父類的屬性時, 不管父類是計算屬性還是儲存屬性, 重寫的過程就是重寫其中的get/set等, 子類的override都是計算屬性的格式
class Person2{ var name:String{ //計算屬性 set{ println("Person2 set") } get{ return "Person2" } } let age: Int = 10 //常量儲存屬性 var height:Int = 175 //變數儲存屬性}class XiaoMing2 : Person2{ override var name:String{ set{ super.name = newValue //將父類的值設定為新值 println("XiaoMing2 set") } get{ return "XiaoMing2" } } override var age : Int{ //如果父屬性是var的話, 必須有get和set get{ println(super.age) return 20 } } override var height :Int{ //重寫觀察屬性: 繼承來的常量儲存屬性,唯讀計算屬性不能添加觀察器. didSet{ //注意有didSet,willSet的地方是不能出現get/set的 println("didset----\(oldValue)") } willSet{ println("willSet----\(newValue)") } }}var xm2 = XiaoMing2()xm2.name = "XM2"println(xm2.age)xm2.height = 10
1.5 防止重寫(final). 與Java一樣
//可將final寫在屬性/方法/類等前面class Person3{ final var name = "Person3"}class XiaoMing3{ //override var name ...//這樣會報錯}
二、構造器
Swift中的構造器無返回值(OC中是返回id的), 它的主要任務是保證新執行個體在第一次使用前完成正確的初始化工作.
init() , 可以重載
2.1 預設構造器與帶參數構造器, 繼承器的重載
class Person4{ var name : String //必須初始化, 或者在建構函式中初始化 //預設, 不帶參數 init(){ //無傳回值 name = "xuneng" } //帶參數 init(name :String){ //預設是以參數名作為外部參數名的 self.name = name + "Hello" //和OC中相同, 用self.(Java中用this) } //帶選擇性參數. 可選類型: 可以為空白,也可以以後賦值. 初始化為nil var age:Int = 10 init(name :String , age:Int?){ self.name = name self.age = age! //選擇性參數必須確定有(加!號)才能賦值 } }var p4 = Person4() //預設就是沒有括弧的var p4_1 = Person4(name: "xn4545945 ") //參數名作為外部參數名var p4_2 = Person4(name: "neng", age: 10)
2.1 指定構造器(Designated initializer)與便利構造器(convenience initializer)
2.1.1 指定構造器: 每個類必須至少有一個,用來確保所有值都進行初始化.(會根據父類的繼承關係往上調用,完成父類的初始化)
//Person4中的3個構造器都是指定構造器, 都需要進行所有成員變數的初始化
2.1.2 便利構造器(加convenience關鍵字):輔助性的構造器.可以用來同一個類中的指定構造器,也可以用來建立一個有特定輸入的執行個體
class Person5{ var name : String //必須初始化, 或者在指定建構函式中初始化 init(name :String){ //指定構造器 self.name = name + "Hello" } convenience init(name :String , height:Int){ //便利構造器. 不需要全部初始化成員變數 self.init(name:name) println(height) }}var p5 = Person5(name: "xn4545945", height: 175)
2.2 構造器鏈(概念): 規範指定構造器與便利構造器間的調用關係.
//1) 規則1: 指定構造器必須調用其父類的指定構造器//2) 規則2: 便利構造器必須調用同一類中調用的其他構造器//3) 規則3: 便利構造器必須以調用一個指定構造器結束
一句話總結上面3個規律: 指定構造器是向上調用的,便利構造器是橫向調用的.
2.3 兩段式構造過程 (概念)
第一個階段:每個儲存型屬性通過引入它們的類的構造器來設定初始值。
第二階階段:當每一個儲存型屬性值被確定後,二階段開始,它給每個類一次機會在新執行個體準備使用之前進一步定製它們的儲存型屬性。
兩段式構造過程的使用讓構造過程更安全,同時在整個類層級結構中給予了每個類完全的靈活性。
Swift 的兩段式構造過程跟 Objective-C中的構造過程類似。最主要的區別在於階段一,Objective-C給每一個屬性賦值 0或空值(比如說 0或 nil)。Swift的構造流程則更加靈活,它允許你設定定製的初始值,並自如應對某些屬性不能以 0或 nil作為合法默 認值的情況。
2.4 構造器的繼承(概念)
與OC不同,
Swift中子類不會預設繼承父類的構造器. (但如果滿足以下2個條件會自動繼承)
1)如果子類沒有定義指定構造器, 那麼他將主動繼承父類的
2)如果子類提供了所有父類指定構造器的實現, 那麼自動繼承父類的便利構造器
class Father{ init(){ println("father init") } convenience init(name:String){ self.init(); println("father convenience init") }}class Son:Father{ override init(){ //子類實現了父類的全部指定構造器, 因而會自動繼承父類的便利構造器 println("son init") }}var son1 = Son()var son2 = Son(name: "xuneng") //自動繼承了父類的便利構造器
2.5 通過閉包和函數來設定屬性的預設值
//閉包的一般格式class SomeClass{ let someProperty : Int = { //整個花括弧表示一個閉包 return 0 }() //這個小括弧不能丟, 表示立即執行閉包. 並傳回值.}1)如果某個儲存屬性的值需要特別定製, 則可以使用閉包或全域函數類提供預設值.
2)當類型建立時, 閉包或函數會被調用,他們的返回值會被當做預設值賦值給這個儲存屬性.
3)使用閉包時, 執行個體的其他部分並沒有初始化, 因而不能在閉包裡面訪問:其他執行個體屬性/self屬性/執行個體方法等.
class Person6{ let name : String = {//可以在閉包裡面做一些複雜的初始化工作 let firstName = "xu" let lastName = "neng" return firstName + lastName }()}var p6 = Person6()println(p6.name)
三、析構(反初始化) deinit
在一個類執行個體被釋放之前, 反初始化函數被立即調用
Swift通過ARC來處理執行個體的記憶體管理, 與OC一樣.
每個類只有一個反初始化函數, 不帶任何參數. 且不允許主動調用.
子類繼承了父類的反初始化函數(釋放順序類似Java. 先釋放子類-->父類)
反初始化話方法能訪問該執行個體的所有屬性
class Person7{ var myMoney:Int init(){ myMoney = 10 } deinit{ myMoney = 0 //可以訪問類中的變數. 但這句沒用. 因為銷毀了,成員變數即不存在了 //可以做一些清理工作 }}var p:Person7? = Person7()println(p!.myMoney)p = nil //可選類型才能設定為nil//p!.myMoney //錯誤, 已設定為nil
參考:
The Swift Programming Language
Apple Dev Center
轉載請註明出處:http://blog.csdn.net/xn4545945
【iOS】Swift類的繼承、構造方法、析構器等複習