Swift基礎(chǔ)語法-類的構(gòu)造函數(shù)


本節(jié)知識點(diǎn)

  1. 構(gòu)造函數(shù)的介紹
  2. 構(gòu)造函數(shù)的基本使用
  3. 自定義構(gòu)造函數(shù)
  4. 屬性與構(gòu)造函數(shù)

1. 構(gòu)造函數(shù)的介紹

  • 構(gòu)造函數(shù)類似于OC中的初始化方法:init方法
  • 默認(rèn)情況下在創(chuàng)建一個類時,必然會調(diào)用一個構(gòu)造函數(shù)
  • 即便是沒有編寫任何構(gòu)造函數(shù)拆挥,編譯器也會提供一個默認(rèn)的構(gòu)造函數(shù)胶征。
  • 如果是繼承自NSObject,可以對父類的構(gòu)造函數(shù)進(jìn)行重寫, 必須在構(gòu)造方法前添加 override關(guān)鍵字
  • 如果基類是自己本身, 則沒有父類, 即不需要在前面添加override關(guān)鍵字
  • 構(gòu)造函數(shù)的格式:
init(參數(shù)列表){ 初始化代碼 }
  • 構(gòu)造函數(shù)的作用: 對實(shí)例對象的內(nèi)容進(jìn)行初始化
    • Swift要求類或者結(jié)構(gòu)體中的存儲屬性(非lazy的)在對象構(gòu)造完畢后要有初始化值, 因此經(jīng)常在構(gòu)造函數(shù)中對屬性初始化
  • 注意:
    • 1.在Swift中類/結(jié)構(gòu)體/枚舉都需要構(gòu)造方法
    • 2.構(gòu)造方法的作用僅僅是用于初始化屬性, 而不是分配內(nèi)容, 分配內(nèi)存是系統(tǒng)幫我們做的
    • 3.構(gòu)造方法是隱式調(diào)用的, 通過 類名稱() 形式創(chuàng)建一個對象就會隱式調(diào)用init()構(gòu)造方法
    • 4.如果所有的存儲屬性都有默認(rèn)值, 可以不提供構(gòu)造方法, 系統(tǒng)會提供一個隱式的構(gòu)造方法
    • 5.如果存儲屬性可以提供缺省, 那么提倡大家使用設(shè)置缺省值的方式, 這樣可以簡化代碼(不用自定義構(gòu)造方法, 不用寫存儲屬性類型)

2. 構(gòu)造函數(shù)使用

2.1 構(gòu)造函數(shù)的基本使用
  • 類的屬性必須有值
  • 如果不是在定義時初始化值,可以在構(gòu)造函數(shù)中賦值
class Person: NSObject {
    var name : String
    var age : Int

    // 重寫了NSObject(父類)的構(gòu)造方法
    override init() {
        name = ""
        age = 0
    }
}
// 創(chuàng)建一個Person對象
let p = Person()
class Person {   // 基類是自己本身
    var name : String = ""
    var age : Int = 0
    
    // 如果沒有明確的實(shí)現(xiàn)默認(rèn)的init()函數(shù),那么擴(kuò)充構(gòu)造函數(shù)時,
    // 會覆蓋默認(rèn)的init()構(gòu)造函數(shù), 就是在創(chuàng)建對象的時候沒有默認(rèn)的創(chuàng)建方式 :  類名()
    init() {  
    // 這里重寫默認(rèn)的 init 方法, 可以什么都不做, 
    // 因?yàn)榍懊嬉呀?jīng)給所有的屬性初始化, 
    // 如果前面有屬性沒有被初始化, 則必須在構(gòu)造函數(shù)中做初始化
    }
}
class Person {
    var name:String = "cdh"
    var age:Int
    func description() -> String {
        return "name = \(name) age = \(age)"
    }
    init(){
        print("init")
        // age 屬性在定義的時候沒有比初始化, 所以必須在這里做初始化
        age = 20
    }
}
//1.分配內(nèi)存
//2.初始化name和age
//3.構(gòu)造方法是隱式調(diào)用的 init()
var p = Person()
p.description() //顯示調(diào)用
//輸出結(jié)果: init

3. 自定義構(gòu)造函數(shù)

3.1 自定義構(gòu)造函數(shù)
  • 很多時候,我們在創(chuàng)建一個對象時, 同時給對應(yīng)屬性賦值
  • 可以自定義構(gòu)造函數(shù)
  • 注意: 如果自定義了構(gòu)造函數(shù),又沒有重寫 init()函數(shù), 則自定義的構(gòu)造函數(shù)會覆蓋默認(rèn)的 init()方法.即不在有默認(rèn)的構(gòu)造函數(shù), 也就不能直接通過 類名() 創(chuàng)建對象
//帶參數(shù)的自定義構(gòu)造函數(shù)
class Person1 {
    var name:String
    var age:Int
    func description() -> String{
        return "name = \(name) age = \(age)"
    }
    //構(gòu)造方法的內(nèi)部參數(shù), 默認(rèn)也是外部參數(shù)
    //而函數(shù)的內(nèi)部參數(shù)默認(rèn)不會當(dāng)做外部參數(shù)
    //而普通的外部函數(shù)的參數(shù), 從第二個開始才會當(dāng)做外部參數(shù)
    //Swift 3.0 之后默認(rèn)所有的參數(shù)即是外部參數(shù)又是內(nèi)部參數(shù)
    //init(name:String, age:Int)
    //構(gòu)造方法對屬性的順序沒有要求,
    //只要保證對象構(gòu)造完時所有存儲屬性被初始化即可
    init(age:Int, name:String) {
        self.name = name
        self.age = age
    }
}
var p1 = Person1(age: 20, name: "cdh")
print("name : \(p1.name), age : \(p1.age)")
3.2 字典轉(zhuǎn)模型(初始化時傳入字典)
  • 真實(shí)創(chuàng)建對象時,更多的是將字典轉(zhuǎn)成模型
  • 注意:
    • 去字典中取出的是NSObject,任意類型.
    • 可以通過as!轉(zhuǎn)成需要的類型,再賦值(不可以直接賦值)
class Person: NSObject {
    var name : String
    var age : Int

    // 自定義構(gòu)造函數(shù),會覆蓋init()函數(shù)
    init(dict : [String : NSObject]) {
        name = dict["name"] as! String
        age = dict["age"] as! Int
    }
}

// 創(chuàng)建一個Person對象
let dict = ["name" : "cdc", "age" : 18]
let p = Person(dict: dict)
3.3 字典轉(zhuǎn)模型(利用KVC轉(zhuǎn)化)
  • 利用KVC字典轉(zhuǎn)模型會更加方便
  • 必須繼承自NSObject
  • 必須在構(gòu)造函數(shù)中先調(diào)用super.init()
  • 注意1:
    • KVC并不能保證會給所有的屬性賦值
    • 因此屬性需要有默認(rèn)值
      • 基本數(shù)據(jù)類型默認(rèn)值設(shè)置為0
      • 對象或者結(jié)構(gòu)體類型定義為可選類型即可(可選類型沒有賦值前為nil)
  • **注意2: **
    • 如果傳入的字典中的鍵值對比當(dāng)前類中的鍵值對多, 則程序會直接奔潰
    • 解決這種情況, 則需要重寫父類的 setValue 方法, 并且什么也不做
      • 注意: override func setValue(value: AnyObject?, forUndefinedKey key: String) {}別寫錯了, 有多個 setValue 函數(shù), 區(qū)別在于參數(shù)不一樣
    • 如果是對父類某一個函數(shù)進(jìn)行重寫,必須在函數(shù)前加上override
class Person: NSObject {
    // 結(jié)構(gòu)體或者類的類型,必須是可選類型.因?yàn)椴荒鼙WC一定會賦值
    var name : String?
    // 基本數(shù)據(jù)類型不能是可選類型,否則KVC無法轉(zhuǎn)化
    var age : Int = 0
    // 自定義構(gòu)造函數(shù),會覆蓋默認(rèn)的 init()函數(shù)
    init(dict : [String : NSObject]) {
        // 必須先初始化對象
        super.init()
        // 調(diào)用對象的KVC方法字典轉(zhuǎn)模型(這里沒有產(chǎn)生歧義的時候 self 可以省略)
        // self.setValuesForKeysWithDictionary(dict)
        setValuesForKeysWithDictionary(dict)
    }
    // 如果傳入的字典中的鍵值對比當(dāng)前類中的鍵值對多, 則程序會直接奔潰
    // 解決這種情況, 則需要重寫父類的 setValue 方法
    // 如果是對父類某一個函數(shù)進(jìn)行重寫,必須在函數(shù)前加上override
    override func setValue(value: AnyObject?, forUndefinedKey key: String) {}
}
// 創(chuàng)建一個Person對象
let dict = ["name" : "cdc", "age" : 18]
let p = Person(dict: dict)

4. 屬性與構(gòu)造函數(shù)

4.1 常量存儲屬性與構(gòu)造方法
  • 常量存儲屬性只能通過缺省值或在構(gòu)造方法中被修改
  • 其它任何地方都不能修改, 并且只能被賦值一次
class Person2 {
    var name:String = "cdh"
    let age:Int
    init(age:Int, name:String){
        self.age = age
        self.name = name
    }
    func description() ->String{
        return "name = \(name) age = \(age)"
    }
}
var p2 = Person2(age: 20, name:"Aarak")
print(p2.description())
//輸出結(jié)果: name = Aarak age = 20
//常量存儲屬性初始化之后不允許被修改, 下面寫法錯誤
//p2.age = 10
4.2 可選屬性與構(gòu)造函數(shù)
  • 類屬性一般都是定義為可選屬性
  • 可選值存儲屬性可以不再構(gòu)造方法中初始化,
  • 也就是說可選值在對象構(gòu)造完畢后不用初始化
  • 其實(shí)如果不對可選存儲屬性進(jìn)行初始化, 默認(rèn)就是nil
class Car {
    let name:String
    init(name:String){
        self.name = name
    }
}
class Person3 {
    let name:String
    var age:Int
    var car:Car?  // 類屬性一般都是定義為可選屬性

    init(age:Int, name:String) {
        self.age = age
        self.name = name
    }
    func description() ->String{
        return "name = \(name) age = \(age) car = \(car)"
    }
}
var p3 = Person3(age: 10, name: "cdh")
print(p3.description())
//輸出結(jié)果: name = cdh age = 10 car = nil
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末矮固,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌敷存,老刑警劉巖漠烧,帶你破解...
    沈念sama閱讀 216,470評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異媒区,居然都是意外死亡驼仪,警方通過查閱死者的電腦和手機(jī)掸犬,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,393評論 3 392
  • 文/潘曉璐 我一進(jìn)店門盏袄,熙熙樓的掌柜王于貴愁眉苦臉地迎上來舷蟀,“玉大人痢毒,你說我怎么就攤上這事庄呈÷饲” “怎么了眨攘?”我有些...
    開封第一講書人閱讀 162,577評論 0 353
  • 文/不壞的土叔 我叫張陵吮廉,是天一觀的道長曲聂。 經(jīng)常有香客問我递惋,道長柔滔,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,176評論 1 292
  • 正文 為了忘掉前任萍虽,我火速辦了婚禮睛廊,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘贩挣。我一直安慰自己喉前,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,189評論 6 388
  • 文/花漫 我一把揭開白布王财。 她就那樣靜靜地躺著卵迂,像睡著了一般。 火紅的嫁衣襯著肌膚如雪绒净。 梳的紋絲不亂的頭發(fā)上见咒,一...
    開封第一講書人閱讀 51,155評論 1 299
  • 那天,我揣著相機(jī)與錄音挂疆,去河邊找鬼改览。 笑死,一個胖子當(dāng)著我的面吹牛缤言,可吹牛的內(nèi)容都是我干的宝当。 我是一名探鬼主播,決...
    沈念sama閱讀 40,041評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼胆萧,長吁一口氣:“原來是場噩夢啊……” “哼庆揩!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起跌穗,我...
    開封第一講書人閱讀 38,903評論 0 274
  • 序言:老撾萬榮一對情侶失蹤订晌,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后蚌吸,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體锈拨,經(jīng)...
    沈念sama閱讀 45,319評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,539評論 2 332
  • 正文 我和宋清朗相戀三年羹唠,在試婚紗的時候發(fā)現(xiàn)自己被綠了奕枢。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片娄昆。...
    茶點(diǎn)故事閱讀 39,703評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖验辞,靈堂內(nèi)的尸體忽然破棺而出稿黄,到底是詐尸還是另有隱情,我是刑警寧澤跌造,帶...
    沈念sama閱讀 35,417評論 5 343
  • 正文 年R本政府宣布杆怕,位于F島的核電站,受9級特大地震影響壳贪,放射性物質(zhì)發(fā)生泄漏陵珍。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,013評論 3 325
  • 文/蒙蒙 一违施、第九天 我趴在偏房一處隱蔽的房頂上張望互纯。 院中可真熱鬧,春花似錦磕蒲、人聲如沸留潦。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,664評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽兔院。三九已至,卻和暖如春站削,著一層夾襖步出監(jiān)牢的瞬間坊萝,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,818評論 1 269
  • 我被黑心中介騙來泰國打工许起, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留十偶,地道東北人。 一個月前我還...
    沈念sama閱讀 47,711評論 2 368
  • 正文 我出身青樓园细,卻偏偏與公主長得像惦积,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子猛频,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,601評論 2 353

推薦閱讀更多精彩內(nèi)容