Swift初始化器及可选链

初始化器

required

  • 用required修饰指定初始化器,表明其所有子类都必须实现该初始化器(通过继承或者重写实现)

  • 如果子类重写了required初始化器,也必须加上required,不用加上override

class Person {
    required init() {}
    
    init(age: Int) {}
}

class Student: Person {
    init(no: Int) {
        super.init(age: 0)
    }
    
    required init() {
        super.init()
    }
}

属性观察器

  • 父类的属性在它自己的初始化器中赋值不会触发属性观察器,但在子类的初始化器中赋值会触发属性观察器
class Person {
    var age: Int {
        willSet {
            print("willSet", newValue)
        }
        didSet {
            print("didSet", oldValue, age)
        }
    }
    
    init() {
        self.age = 0
    }
}

class Student: Person {
    override init() {
        super.init()
        self.age = 1
    }
}

可失败初始化器

  • 类、结构体、枚举都可以使用init?定义可失败初始化器
class Person {
    var name: String
    
    init?(name: String) {
        if name.isEmpty {
            return nil
        }
        self.name = name
    }
}
  • 不允许同时定义参数标签、参数个数、参数类型相同的可失败初始化器和非可失败初始化器

  • 可以用init!定义隐式解包的可失败初始化器

  • 可失败初始化器可以调用非可失败初始化器,非可失败初始化器调用可失败初始化器需要进行解包

class Person {
    var name: String
    
    init?(name: String) {
        if name.isEmpty {
            return nil
        }
        self.name = name
    }
    
    convenience init() {
        self.init(name: "")!
    }
}
  • 如果初始化器调用一个可失败初始化器导致初始化失败,那么整个初始化过程都失败,并且之后的代码都停止执行

  • 可以用一个非可失败初始化器重写一个可失败初始化器,但反过来是不行的。

反初始化器(deinit)

  • deinit叫做反初始化器,类似于C++的析构函数、OC中的dealloc方法

      当类的实例对象被释放内存时,就会调用实例对象的deinit方法
    
class Person {
    deinit {
        print("Person对象销毁了")
    }
}
  • deinit不接受任何参数,不能写小括号,不能自行调用

  • 父类的deinit能被子类继承

  • 子类的deinit实现执行完毕后会调用父类的deinit

可选链(Optional Chaining)

class Car {
    var price = 0
}

class Dog {
    var weight = 0
}

class Person {
    var name: String = ""
    var dog: Dog = Dog()
    var car: Car? = Car()
    
    func age() -> Int {
        18
    }
    
    func eat() {
        print("Person eat")
    }
    
    subscript(index: Int) -> Int {
        return index
    }
}

var person: Person? = Person()
var age = person?.age()//Int? Optional(18)
var age1 = person!.age() // Int
var name = person?.name //String?
var index = person?[6] // Int?
  • 如果可选项为nil,调用方法、下标、属性失败,结果为nil

  • 如果可选项不为nil,调用方法、下标、属性成功,结果会被包装成可选项

  • 如果结果本来就是可选项,不会进行再次包装

判断方法有没有调用成功:

if let age = person?.age() { // ()?
    print("调用age成功", age)
} else {
    print("调用age失败")
}

形成可选链:

  • 多个?可以链接在一起

如果链中任何一个节点是nil,那么整个链就会调用失败,可选链应用的地方还是很多的,在OC里面我们通常会加很多判断以避免崩溃,在Swift里面,因为有了可选链会减少很多我们自己的判断,提高了安全性。

var dog = person?.dog // Dog?
var weight = person?.dog.weight // Int?
var price = person?.car?.price // Int?
var scores = [
    "Jack" : [86, 82, 84],
    "Rose" : [79, 94, 81]
]

scores["Jack"]?[0] = 100
scores["Rose"]?[2] += 10
scores["Kate"]?[0] = 88
var num1: Int? = 5
num1? = 10 // Optional(10)

var num2: Int? = nil
num2? = 10 // nil
var dict: [String : (Int, Int) -> Int] = [
    "sum" : (+), //两个Int类型相加,返回一个Int类型
    "difference" : (-)
]

var result = dict["sum"]?(10, 20) // Optional(30), Int?

你可能感兴趣的:(Swift初始化器及可选链)