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() {
        
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章