iOS學習筆記43-Swift(三)類

1、Swift的類class

做爲一門面向對象語言,類也是Swift的很是重要的類型,咱們先來看下一個簡單的類swift

//Swift中一個類能夠不繼承於任何其餘基類,那麼此類自己就是一個基類
class Person {
    //定義屬性
    var name:String
    var height = 0.0
    //構造器方法,注意若是不編寫構造方法默認會自動建立一個無參構造方法
    init(name:String){
        self.name = name
    }
    //析構器方法,在對象被釋放時調用,相似於ObjC的dealloc,注意這裏沒有括號和參數,沒法直接調用
    deinit{
        println("deinit...")
    }
    //定義對象方法
    func showMessage(){
        println("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"
println(p.name) //結果:XiaoMing
//「===」表示等價於,這裏不能使用等於「==」,等於用於比較值相等,p和p2是不一樣的值,可是指向的對象相同
if p === p2 { 
    println("p===p2") //p等價於p2,表示兩者指向同一個對象
}

2、屬性

Swift中淡化了成員屬性的概念,把屬性分爲兩種:ide

  1. 存儲屬性
    不管從概念上仍是定義方式上來看,存儲屬性更像其餘語言中的成員變量,可是不一樣的是:
  • 能夠控制讀寫操做(var表示可讀可寫,let表示只讀)
  • 經過屬性監視器來屬性的變化(willSetdidSet
  • 快速實現懶加載功能(lazy修飾)
  1. 計算屬性
    計算屬性並不直接存儲一個值,而是提供getter來獲取一個值,或者利用setter來間接設置其餘屬性。
下面是對象屬性使用實例:
class Account {
    //定義存儲屬性,設置默認值,添加屬性監聽器
    var balance:Double = 0.0{
        //即將賦值時調用
        willSet{
            //注意此時修改balance的值沒有用
            self.balance = 2.0
            //newValue表示即將賦值的新值,而且在屬性監視器內部調用屬性不會引發監視器循環調用
            println("Account.balance willSet,newValue=\(newValue),value=\(self.balance)")
        }
        //賦值完成後調用
        didSet{
            //注意此時修改balance的值將做爲最終結果
            self.balance = 3.0
            //oldValue表示已經賦值的舊值,而且在屬性監視器內部調用屬性不會引發監視器循環調用
            println("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表示即將賦值的新值,這裏是分割字符串
            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(){
        println("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=0.0
Account.balance didSet,oldValue=10,value=3.0
*/
println("p.account.balance=\(p.account.balance)") //結果:p.account.balance=3.0
  1. 計算屬性並不直接存儲一個值,而是提供getter來獲取一個值,或者利用setter來間接設置其餘屬性;
  2. lazy屬性必須有初始值,必須是變量不能是常量,由於常量在構造完成以前就已經肯定了值;
  3. 在構造對象方法以前存儲屬性必須有值(可選類型除外),不管是變量屬性仍是常量屬性,這個值既能夠在屬性建立時指定,也能夠在構造方法內指定;
  4. 存儲屬性的默認值設置不會引發屬性監視器的調用(另外在構造方法中賦值也不會引發屬性監視器調用),只有在外部設置存儲屬性纔會引發屬性監視器調用;
除了上面的對象屬性外,咱們還能夠定義類的屬性:
class Student {
    //定義類的屬性只須要在前面加static關鍵字便可,也是分爲存儲屬性和計算屬性,這裏是計算屬性
    static var skin:Array<String>{
        //只定義了getter,表示該計算屬性是隻讀的
        get{
            return ["yellow", "white", "black"]
        }
    }
}
//讀取類的屬性
for color in Student.skin {
    println(color)
}

3、方法

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{
        println("deinit...")
    }
    //3.對象方法
    func modifyInfoWithAge(age:Int, height:Double){
        self.age = age
        self.height = height
    }
    //4.類方法,使用class修飾的方法便是類方法
    class func showClassName(){
        println("Class name is Person")
    }      
}
//經過便利構造方法建立對象
var p = Person(name: "liuting")
//調用對象方法
p.modifyInfoWithAge(22,height: 170)
//調用類方法
Person.showClassName()
  1. 除構造方法、析構方法外,其餘方法的參數默認除了第一個參數是局部參數,從第二個參數開始既是局部參數又是外部參數。可是,對於函數,默認狀況下只有默認參數既是局部參數又是外部參數,其餘參數都是局部參數。
  2. 構造方法的全部參數默認狀況下既是外部參數又是局部參數
  3. 只有便利構造器方法才能調用當前類的指定構造方法
  4. 有參數的指定構造器方法會覆蓋調用默認的無參構造器方法
  5. 一個對象被釋放前,先自動調用本身的析構方法,而後一層一層往上調用父類的析構方法

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"])
println("r[0]=\(record[0])") //結果:r[0]=liuting
record["sex"] = "female"
println(record["sex"]) //結果:female

5、繼承

和ObjC同樣,Swift也是單繼承的(能夠實現多個協議,此時協議放在後面),子類能夠調用父類的屬性、方法,重寫父類的方法,添加屬性監視器,甚至能夠將只讀屬性重寫成讀寫屬性。code

//定義一個父類
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(){
        println("name=\(self.fullName),age=\(self.age)")
    }
    //經過final聲明,子類沒法重寫
    final func sayHello(){
        println("hello world.")
    }
}
//定義子類
class Student: Person {
    //重寫屬性,爲屬性添加監視器,重寫都須要加override關鍵字
    override var firstName:String{
        willSet{
            println("firstName willSet")
        }
        didSet{
            println("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() {
        println("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. 只有指定構造方法才能調用父類的構造方法。
  2. 若是父類中存在有參數的指定構造方法,子類的指定構造方法不會自動調用父類無參的指定構造方法。
  3. 若是父類僅有一個無參構造方法(不論是否包含便利構造方法),子類的構造方法默認就會自動調用父類的無參構造方法(這種狀況下能夠不用手動調用)。
  4. 常量屬性只能在定義它的類的構造方法中初始化,不能在子類中初始化
  5. 一個對象被釋放前,先自動調用本身的析構方法,而後一層一層往上調用父類的析構方法。
  6. 便利構造方法必須調用同一個類中的其餘指定構造方法(能夠是指定構造方法或者便利構造方法),不能直接調用父類構造方法。

有什麼問題可在下方評論區中提出!O(∩_∩)O哈!
相關文章
相關標籤/搜索