swift-構造函數(init)

說在前面的話

構造過程是使用類、結構體或枚舉類型的實例之前的準備過程。在新實例使用前有個過程是必須的,它包括設置實例中每個存儲屬性的初始值和執行其他必須的設置或構造過程。

巨大的建築,總是由一木一石疊起來的,我們何妨做做這一木一石呢?我時常做些零碎事,就是爲此 ------《迅哥》

存儲屬性的初始賦值

主要根據參數列表來確定 是用哪個構造器
在swift中 不允許出現 沒有初始化的變量 和 常量 所以這裏我們給了 num:int?

class count{
    
    var num:Int?
    
    init() {
        print("加載一些資源")
    }
    
    init(num:Int) {
        self.num=num
        print("第二個")
    }
    
}

var s1 = count()
var s2 = count(num:1)

默認構造器

適用於類,結構體和枚舉類型 無需實現 有swift編譯器 自動生成 即在定義屬性的時候賦予初始值

啥話不說 就是在類中給予 屬性賦予初始值 或者 屬性值爲nil

class studnet2{

    var name:String = "sj"
    var age:Int = 19
    var sex:String?
    
    func seyHello() {
        print("\(self.age)\(self.name)")
    }
}

var s4 = studnet2()
s4.seyHello()

指定構造器

指定構造器是類中最主要的構造器。一個指定構造器將初始化類中提供的所有屬性,並調用合適的父類構造器讓構造過程沿着父類鏈繼續往上進行。

class studnet{
    
    var name:String?
    var age:Int?
    
    init(name:String,age:Int) {
        self.name=name
        self.age=age
    }
    
    func seyHello() {
        print("\(self.age!)\(self.name!)")
    }

}


var s3 = studnet(name: "sj", age: 19)
s3.seyHello()// sj  19

便攜構造器

是類中比較次要的 輔助型構造器 我們可以在便攜構造器中調用同一個類中的指定構造器 併爲其參數提供默認的值 也可以定義便攜構造器創建一個用途或者特定輸入的實力

三條規則:
1:指定構造器必須調用器直接父類的指定在構造器
2:便攜構造器必須調用同一類中定義的其他構造函數
3:便攜構造器必須最終以調用一個指定構造器

基本語法:


    convenience init(){

    }

使用例子;

一個基類 person 屬性:name

class person{
    
    var name:String
    
    
    //指定
    init(name:String) {
        self.name=name
    }
    
    //便攜
    convenience init(){
        //現調用當前的其他構造器
        self.init(name: "ssj")
        //必須先使用另一個有效的構造器 然後在進行當前內容的初始化
        self.name="sssss"
    }
    
    func seyHello() {
        print("\(self.name)")
    }
    
}
class student5:person{
    
    var Lever:Int
    
    init(name:String,Lever:Int) {
        
        //子類初始化應優先初始化派生的新屬性
        self.Lever=Lever
        //在使用父類的方式 初始化父類的屬性
        super.init(name: name)
        //然後在可以對父類的屬性重新初始化
        self.name=name
    }
    
    convenience init(){
        self.init(name:"saads",Lever:1)
        print("studeng累的便攜構造器輸出了")
    }
    
    override func seyHello() {
        print("\(name),\(Lever)")
    }

}

class ItStudent:student5{
    
    var conName:String
    
    init(name:String,Lever:Int,conName:String) {
        self.conName=conName
        super.init(name:name,Lever:Lever)
    }
    
    convenience init(conName:String) {
        self.init(name:"ItBoy",Lever:100,conName:conName)
        print("ItBoy的便攜構造器 輸出了  又參數")
    }
    
    convenience init() {
        //先調用當前類的指定構造函數
        self.init(name:"ItBoy",Lever:100,conName:"NIL")
        print("ItBoy的便攜構造器 輸出了   五參數")
    }
    
    override func seyHello() {
        print("\(conName),\(name),\(Lever)")
    }
    
}
var n = person()
n.seyHello()

//使用指定構造器
var m = ItStudent(conName: "ItSSJ")
m.seyHello()
//使用便攜構造器
m = ItStudent()
m.seyHello()

//使用指定構造器
var b = student5(name: "ssk", Lever: 1)
b.seyHello()
//使用便攜構造器
b = student5()
b.seyHello()

成員構造器

他是結構體特有的 他的默認初始化提供的一種形式

struct student{
    var name:String
    var age:Int
    
    func seyHello() {
        print("\(name)\(age)")
    }
 
}

var xiaom = student(name: "ssssj", age: 23)
xiaom.seyHello()

成員構造器 就是針對結構體 的一種形式 他會在實力化的時候給予 結構體的屬性一種默認的 初始化方式

可失敗構造器

有時,定義一個構造器可失敗的類,結構體或者枚舉是很有用的。這裏所指的“失敗” 指的是,如給構造器傳入無效的形參,或缺少某種所需的外部資源,又或是不滿足某種必要的條件等。

可失敗構造器的一般形式:
init?(){} //需要解包
init!(){} //不需要解包

爲了妥善處理這種構造過程中可能會失敗的情況。你可以在一個類,結構體或是枚舉類型的定義中,添加一個或多個可失敗構造器。其語法爲在 init 關鍵字後面添加問號(init?)。


不需要解包

class person2{
    
    
    var anme:String
    var age:Int
    
    init!(name:String,age:Int) {
           self.anme=name
           self.age=age
           
           if age<0 {
               return nil
               print("初始化失敗")
           }
       }
    
    func seyHello() {
        print("\(anme)")
    }
    

}

var ssj =  person2(name: "ssl", age: 0)
ssj!.seyHello()  


需要解包

class person2{
    
    var anme:String
    var age:Int
    
    init?(name:String,age:Int) {
        self.anme=name
        self.age=age

        if age<0 {
           return nil
            print("初始化失敗")
        }
    }
    
  
    
    func seyHello() {
        print("\(anme)")
    }
    

}

var ssj =  person2(name: "ssl", age: 0)
ssj?.seyHello()

構造失敗的傳遞

類、結構體、枚舉的可失敗構造器可以橫向代理到它們自己其他的可失敗構造器。類似的,子類的可失敗構造器也能向上代理到父類的可失敗構造器。

可能失敗構造器的傳播(調用)
1.可能失敗的構造器可以調用同一個類中的普通構造器
2.普通構造器不能調用同一個類中的可能失敗構造器
3.結構體中, 普通構造器卻可以調用同一個結構體中可能失敗的構造器

可能失敗構造器的重寫
1.子類可以用可能失敗的構造器或者普通的構造器重寫父類中的可能失敗的構造器
2.子類的普通構造器不能向上調用父類的可能失敗的構造器
3.子類的可能失敗的構造器可以調用父類的可能失敗的構造器

class Person {
     
    var name: String = ""
     
    // 定義指定構造器
    init(){
         
    }
     
    // 定義可能失敗構造器
    init?(name: String) {
        if !name.isEmpty {
            self.name = name
        } else {
            print("構造失敗")
            return nil
        }
    }
}
class Man: Person {
     
    var sex = "男"
     
    // 使用普通構造器重寫父類的構造器
    override init(name: String) {
        // 由於該構造器是普通構造器, 因此不能調用父類的顯式(?)可能失敗的構造器
        // 可以調用父類的隱式(!)可能失敗的構造器 或 調用父類中的普通構造器
        super.init()
    }
 
    // 定義可能失敗構造器
    init!(name: String, sex: String) {
        // 子類中的可能失敗構造器可以調用父類的可能失敗構造器
        super.init(name: name)
        if sex == "其他" {
            print("構造失敗")
            return nil
        }
        self.sex = sex
    }
}
 
let p1 = Man(name: "")
print(p1)
let p2 = Man(name: "rinpe", sex: "男")
print(p2 == nil)
let p3 = Man(name: "", sex: "女")
print(p3 == nil)

必要構造器

必要構造函數
在類的構造函數前添加required 修飾符來表明表明它是一個必要構造函數.
注意:
當子類重寫父類的必要構造函數時,不需要添加 override 修飾符,必須在子類的構造函數前也要添加 required

class Parent{
    required init() {
        
    }
}
class Son:Parent{
    required init() {
        
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章