美文网首页
Swift 初始化

Swift 初始化

作者: Arthur澪 | 来源:发表于2020-02-20 14:18 被阅读0次

    初始化器initializer

    类、结构体、枚举都可以定义初始化器,类似init方法。

    类的初始化

    类有2种初始化器:
    指定初始化器(designated initializer)
    便捷初始化器(convenience initializer)

    // 指定初始化器 
    init(parameters) {
        statements 
    }
    // 便捷初始化器, 关键字 convenience
    convenience init(parameters) {
        statements 
    } 
    

    每个类至少有一个指定初始化器,它是类的默认初始化器、主要初始化器
    一个类通常只有一个指定初始化器。偏向于少量 。

    • 相互调用规则
      指定初始化器必须从它的直系父类调用指定初始化器
      便捷初始化器必须从相同的类里调用另一个初始化器
      便捷初始化器最终必须调用一个指定初始化器,为了保证安全,保证所有属性都被初始化。
    class Person {
        var name: String
        var age: Int
        var height: Int {
            get {
                return age * 10;
            }
        }
        // 指定初始化器
        init(name: String, age: Int) {
            self.name = name;
            self.age = age;
        }
        
        // 以下是 便捷初始化器
        convenience init(name: String){
            self.init(name: name, age: 0);
        }
     
        convenience init (age: Int) {
            self.init(name: "", age: age);
        }
     
        convenience init(){
            self.init(name: "", age: 0);
        }
    }
    
    var ppp = Person(age: 10);
    var ppp1 = Person(name: "Alex");
    var PPP2 = Person(name: "alex", age: 10);
    

    Swift在编码安全方面是煞费苦心,为了保证初始化过程的安全,设定了两段式初始化、 安全检查。

    -

    安全检查

    -

    重写init

    当重写父类的指定初始化器时,都必须加上override
    如果子类写了一个匹配父类便捷初始化器的初始化器,不用加override
    严格来说,子类无法重写父类的便捷初始化器。因为父类的便捷初始化器永远不会通过子类直接调用。

    自动继承

    如果子类没有自定义任何指定初始化器,它会自动继承父类所有的指定初始化器
    如果子类提供了父类所有指定初始化器的实现(要么通过方式1继承,要么重写)
    子类自动继承所有的父类便捷初始化器
    就算子类添加了更多的便捷初始化器,这些规则仍然适用
    子类以便捷初始化器的形式重写父类的指定初始化器,也可以作为满足规则2的一部分

    required

    required修饰指定初始化器,表明其所有子类都必须实现(通过继承或者重写实现)
    如果子类重写了required初始化器,也必须加上required,不用加override

    属性观察器

    父类的属性在它自己的初始化器中赋值,不会触发属性观察器。
    但在子类的初始化器中赋值,会触发属性观察器。

    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 
        }
    }
    // willSet 1
    // didSet 0 1
    var stu = Student()
     
    

    可失败初始化器

    可以使用init?定义

    class Person {
        var name: String
        init?(name: String) {
            if name.isEmpty  {
                return nil
            }
            self.name = name
        }
    }
    

    不允许同时定义参数标签、参数个数、参数类型相同的可失败初始化器和非可失败初始化器
    可以用init!定义隐式解包的可失败初始化器
    可失败初始化器可以调用非可失败初始化器,非可失败初始化器调用可失败初始化器需要进行解包
    如果初始化器调用一个可失败初始化器导致初始化失败,那么整个初始化过程都失败,并且之后的代码都停止执行
    可以用一个非可失败初始化器重写一个可失败初始化器,但反过来是不行的

    反初始化器(deinit)

    类似于 OC中的dealloc,当类的实例对象被释放内存时,就会调用实例对象的deinit

     class Person {
        deinit {
            print("Person对象销毁了") 
        }
    }
    

    deinit不接受任何参数,不能写小括号,不能自行调用
    父类的deinit能被子类继承
    子类的deinit实现执行完毕后会调用父类的deinit

    相关文章

      网友评论

          本文标题:Swift 初始化

          本文链接:https://www.haomeiwen.com/subject/bpntqhtx.html