iOS學習筆記43 Swift(三)類

執著丶執念發表於2018-06-02

###一、Swift的類class 作為一門物件導向語言,類也是Swift的非常重要的型別,我們先來看下一個簡單的類

//Swift中一個類可以不繼承於任何其他基類,那麼此類本身就是一個基類
class Person {
    //定義屬性
    var name:String
    var height = 0.0
    //構造器方法,注意如果不編寫構造方法預設會自動建立一個無參構造方法
    init(name:String){
        self.name = name
    }
	//析構器方法,在物件被釋放時呼叫,類似於ObjC的dealloc,注意這裡沒有括號和引數,無法直接呼叫
    deinit{
        print("deinit...")
    }
    //定義物件方法
    func showMessage(){
        print("name=\(name),height=\(height)")
    }    
}
//建立類的物件
var p = Person(name: "Liuting")
p.height = 170.0
p.showMessage() //結果:name=Liuting,height=170.0
 
//類是引用型別
var p2 = p
p2.name = "XiaoMing"
print(p.name) //結果:XiaoMing
//“===”表示等價於,這裡不能使用等於“==”,等於用於比較值相等,p和p2是不同的值,但是指向的物件相同
if p === p2 { 
    print("p===p2") //p等價於p2,表示二者指向同一個物件
}
複製程式碼

###二、屬性 Swift中淡化了成員屬性的概念,把屬性分為兩種:

  1. 儲存屬性: 無論從概念上還是定義方式上來看,儲存屬性更像其他語言中的成員變數,但是不同的是:
  • 可以控制讀寫操作(var表示可讀可寫,let表示只讀)
  • 通過屬性監視器來屬性的變化(willSetdidSet
  • 快速實現懶載入功能(lazy修飾)
  1. 計算屬性: 計算屬性並不直接儲存一個值,而是提供getter來獲取一個值,或者利用setter來間接設定其他屬性。

######下面是物件屬性使用例項:

class Account {
    //定義儲存屬性,設定預設值,新增屬性監聽器
    var balance:Double = 0.0{
        //即將賦值時呼叫
        willSet{
            //注意此時修改balance的值將作為最終結果
            self.balance = 2.0
            //newValue表示即將賦值的新值,並且在屬性監視器內部呼叫屬性不會引起監視器迴圈呼叫
            print("Account.balance willSet,newValue=\(newValue),value=\(self.balance)")
        }
        //賦值完成後呼叫
        didSet{
            //注意此時修改balance的值將作為最終結果
            self.balance = 3.0
            //oldValue表示已經賦值的舊值,並且在屬性監視器內部呼叫屬性不會引起監視器迴圈呼叫
            print("Account.balance didSet,oldValue=\(oldValue),value=\(self.balance)")
        }
    }
}
class Person {
    //firstName、lastName、age是儲存屬性
    var firstName:String //var定義表示該儲存屬性可讀可寫
    var lastName:String
    let age:Int //let定義表示該儲存屬性只讀

    //屬性的懶載入,第一次訪問才會初始化
    lazy var account = Account()//在Swift中懶載入的屬性不一定就是物件型別,也可以是基本型別

    //fullName是一個計算屬性,在get、set方法中不能直接訪問計算屬性,否則會引起迴圈呼叫
    var fullName:String{
        //獲取該計算屬性時呼叫
        get{
            return firstName + "." + lastName
        }
        //設定該計算屬性時呼叫
        set{
            //set方法中的newValue表示即將賦值的新值,這裡是分割字串(Swift1的方法,Swift2以後改了)
            let array = split(newValue, maxSplit: Int.max, 
                                allowEmptySlices: false, 
                                     isSeparator: {$0=="."})
            if array.count == 2 {
                firstName = array[0]
                lastName = array[1]
            }
        }
    }
    //構造器方法,注意如果不編寫構造方法預設會自動建立一個無參構造方法
    init(firstName:String, lastName:String, age:Int){
        self.firstName = firstName
        self.lastName = lastName
        self.age = age
    }
    //定義方法
    func showMessage(){
        print("name=\(self.fullName),age=\(self.age)")
    }
}
//建立物件
var p = Person(firstName: "Liu", lastName: "Ting", age:22)
p.showMessage() //結果:name=Liu.Ting,age=22
p.fullName = "Liu.HAHA" //設定計算屬性
p.showMessage() //結果:name=Liu.HAHA,age=22

p.account.balance = 10
/* 下面是儲存屬性監聽器方法列印:
Account.balance willSet,newValue=10,value=2.0
Account.balance didSet,oldValue=0,value=3.0
*/
print("p.account.balance=\(p.account.balance)") //結果:p.account.balance=3.0
複製程式碼
  1. 計算屬性並不直接儲存一個值,而是提供getter來獲取一個值,或者利用setter來間接設定其他屬性;
  1. lazy屬性必須有初始值,必須是變數不能是常量,因為常量在構造完成之前就已經確定了值;
  2. 在構造物件方法之前儲存屬性必須有值(可選型別除外),無論是變數屬性還是常量屬性,這個值既可以在屬性建立時指定,也可以在構造方法內指定;
  3. 儲存屬性的預設值設定不會引起屬性監視器的呼叫(另外在構造方法中賦值也不會引起屬性監視器呼叫),只有在外部設定儲存屬性才會引起屬性監視器呼叫;

######除了上面的物件屬性外,我們還可以定義類的屬性:

class Student {
    //定義類的屬性只需要在前面加static關鍵字即可,也是分為儲存屬性和計算屬性,這裡是計算屬性
    static var skin:Array<String>{
        //只定義了getter,表示該計算屬性是隻讀的
        get{
            return ["yellow", "white", "black"]
        }
    }
}
//讀取類的屬性
for color in Student.skin {
    print(color)
}
複製程式碼

###三、方法 ######Swift的類中的方法可分為以下幾個類別:

  1. 構造器方法
  • 預設構造器方法(當存在有引數的指定構造器方法,被覆蓋)
  • 指定構造器方法
  • 便利構造器方法
  1. 析構器方法
  2. 物件方法
  3. 類方法

######以下是方法使用例項:

class Person {
    //定義屬性
    var name:String
    var height:Double
    var age = 0
    //1.2.指定構造器方法,注意如果不編寫構造方法,預設會自動建立一個無參構造方法
    init(name:String, height:Double, age:Int){
        self.name = name
        self.height = height
        self.age = age
    }
    //1.3.便利構造方法,通過呼叫指定構造方法、提供預設值來簡化構造方法實現
    convenience init(name:String){
        self.init(name:name, height:0.0, age:0)
    }
	//2.析構方法,在物件被釋放時呼叫,注意此方法沒有括號,沒有引數,無法直接呼叫
    deinit{
        print("deinit...")
    }
    //3.物件方法
    func modifyInfoWithAge(age:Int, height:Double){
        self.age = age
        self.height = height
    }
    //4.類方法,使用class修飾的方法即是類方法
    class func showClassName(){
        print("Class name is Person")
    }      
}
//通過便利構造方法建立物件
var p = Person(name: "liuting")
//呼叫物件方法
p.modifyInfoWithAge(22,height: 170)
//呼叫類方法
Person.showClassName()
複製程式碼
  1. 除構造方法、析構方法外,其他方法的引數預設除了第一個引數是區域性引數,從第二個引數開始既是區域性引數又是外部引數。但是,對於函式,預設情況下只有預設引數既是區域性引數又是外部引數,其他引數都是區域性引數。
  1. 構造方法的所有引數預設情況下既是外部引數又是區域性引數
  2. 只有便利構造器方法才能呼叫當前類的指定構造方法
  3. 有引數的指定構造器方法會覆蓋呼叫預設的無參構造器方法
  4. 一個物件被釋放前,先自動呼叫自己的析構方法,然後一層一層往上呼叫父類的析構方法

###四、下標指令碼 下標指令碼是一種訪問集合的快捷方式,如果我們自定義的類具有集合型別的功能,我們可以定義下標指令碼來快捷訪問該類屬性,定義下標指令碼是通過關鍵字subscript進行的。

class Record {
    //定義屬性,store是Record內部的儲存結構,這裡是字典
    var store:[String:String]
    //指定構造方法
    init(data:[String:String]){
        self.store = data
    }
    //下標指令碼,下標索引為整形(注意也可以實現只有getter的只讀下標指令碼)
    subscript(index:Int) -> String{
        get{
			//字典的key進行排序後根據Index整形索引獲取字典的值
            var key = sorted(Array(self.store.keys))[index]
            return self.store[key]!
        }
        set{
			//字典的key進行排序後根據Index整形索引設定字典的值
            var key = sorted(Array(self.store.keys))[index]
            self.store[key] = newValue //newValue和屬性一樣使用
        }
    }
    //下標指令碼,下標索引為字串
    subscript(key:String) -> String{
        get{
            return store[key]!
        }
        set{
            store[key] = newValue
        }
    }
}
//建立物件
var record = Record(data:["name":"liuting","sex":"male"])
print("r[0]=\(record[0])") //結果:r[0]=liuting
record["sex"] = "female"
print(record["sex"]) //結果:female
複製程式碼

###五、繼承 和ObjC一樣,Swift也是單繼承的(可以實現多個協議,此時協議放在後面),子類可以呼叫父類的屬性、方法,重寫父類的方法,新增屬性監視器,甚至可以將只讀屬性重寫成讀寫屬性。

//定義一個父類
class Person {
    var firstName:String
	var lastName:String
    var age:Int = 0
    var fullName:String{
        get{
            return firstName + " " + lastName
        }
    }
    //指定構造方法
    init(firstName:String,lastName:String){
        self.firstName = firstName
        self.lastName = lastName
    }
    //物件方法
    func showMessage(){
        print("name=\(self.fullName),age=\(self.age)")
    }
    //通過final宣告,子類無法重寫
    final func sayHello(){
        print("hello world.")
    }
}
//定義子類
class Student: Person {
    //重寫屬性,為屬性新增監視器,重寫都需要加override關鍵字
    override var firstName:String{
        willSet{
            print("firstName willSet")
        }
        didSet{
            print("firstName didSet")
        }
    }
    //新增子類屬性
    var score:Double
     
    //子類指定構造方法一定要呼叫父類構造方法
    //並且必須在子類儲存屬性初始化之後呼叫父類構造方法
    init(firstName:String, lastName:String, score:Double){
        self.score = score
        super.init(firstName: firstName, lastName: lastName)
    }
    //便利構造方法
    convenience init(){
        self.init(firstName:"", lastName:"", score:0)
    }
    //將只讀屬性重寫成了可寫屬性
    override var fullName:String{
        get{
            return super.fullName;
        }
        set{
            let array = split(newValue, maxSplit: Int.max, 
								allowEmptySlices: false, 
									 isSeparator: { $0 == "." })
            if array.count == 2 {
                firstName = array[0]
                lastName = array[1]
            }
        }
    }
    //重寫物件方法
    override func showMessage() {
        print("name=\(self.fullName),age=\(self.age),score=\(self.score)")
    }
     
}
//建立子類物件
var p = Student()
p.firstName = "liu"
p.showMessage() //結果:name=liu,age=0,score=0
p.fullName = "Liu.Ting"
p.showMessage() //結果:name=Liu.Ting,age=0,score=0
p.sayHello()
複製程式碼
  1. 只有指定構造方法才能呼叫父類的構造方法。
  1. 如果父類中存在有引數的指定構造方法,子類的指定構造方法不會自動呼叫父類無參的指定構造方法。
  2. 如果父類僅有一個無參構造方法(不管是否包含便利構造方法),子類的構造方法預設就會自動呼叫父類的無參構造方法(這種情況下可以不用手動呼叫)。
  3. 常量屬性只能在定義它的類的構造方法中初始化,不能在子類中初始化
  4. 一個物件被釋放前,先自動呼叫自己的析構方法,然後一層一層往上呼叫父類的析構方法。
  5. 便利構造方法必須呼叫同一個類中的其他指定構造方法(可以是指定構造方法或者便利構造方法),不能直接呼叫父類構造方法。

iOS學習筆記43 Swift(三)類

#####有什麼問題可在下方評論區中提出!O(∩_∩)O哈!

相關文章