美文网首页
Swift开发--Designated、Convenience和

Swift开发--Designated、Convenience和

作者: 无题007 | 来源:发表于2017-03-07 14:27 被阅读194次

    开篇

    在今天之前,我一直是不愿意写博客的,感觉写博客有些浪费时间,(其实这都是借口,主要还是因为懒想多玩局LOL,想多看个电影)正所谓一入坑门深似海,从此游戏成路人啊~

    摘要

    摘要:Swift有着超级严格的初始化方法,不仅强化了designated初始化方法的地位,所有不加修饰的init方法都需要在方法中确保非Optional的实例变量被赋值初始化,而在子类中,也强制调用super版本的designated初始化。

    进入正题

    swift为什么要这样做呢?因为在OC中init方法不那么安全,没有人可以保证init只被调用一次,也没有人能保证在初始化之后,实例的各个变量都完成初始化,甚至如果在初始化里使用属性进行设置的话,还可能会造成各种问题。虽然Apple也明确说明了不应该在init中使用属性来访问,但这并不是编译器强制的,因此还是会有开发者犯这样的错。
    所以swift规定了严格的初始化方法,强化了designated初始化方法的地位。swift中不加修饰的init方法都需要在方法中保证所有非可选( Optional)的实例变量被赋值初始化,而在子类中也强制调用super版本的designated初始化,所以无论如何走何种路径,被初始化的对象总是可以完成完整的初始化的。

    class ClassA {
        let numA: Int
        init(num: Int) {
            numA = num
        }
    }
    
    class ClassB: ClassA {
        let numB: Int
    
        override init(num: Int) {//重写父类的方法
            numB = num + 1
            super.init(num: num)
        }
    }
    

    在上面的示例代码中,注意init里我们可以对let的实例变量进行赋值,这是初始化方法的重要特点。在swift中let声明的值是常量,无法被写入赋值,这对构建线程安全的API十分有用。因为swift中init只被调用一次,所以在init中我们可以为常量进行赋值,不用担心引起线程安全的问题。

    与designated初始化相对应的是在init前加上convenience 关键字的初始化方法,这是swift初始化方法中的“二等公民”,只作为补充和提供使用上的方便。所有的convenience方法都必须调用同一个类中的designated初始化完成设置,另外convenience的初始化方法是不能被子类重写或从子类中以super的方式被调用的。

    class ClassAA {
        let numA: Int
        init(num: Int) {
            numA = num
        }
        convenience init(bigNum: Bool) {
            self.init(num: bigNum ? 10000 : 1) // 所有的 convenience 初始化方法都必须调用同一个类中的 designated 初始化完成设置
        }
    }
    
    class ClassBB: ClassAA {
        let numB: Int
        override init(num: Int) {
            numB = num + 1
            super.init(num: num)
        }
    }
    

    只要在子类中实现重写了父类的convenience方法所需要的init方法的话,我们在子类中就可以使用父类的convenience初始化方法了。例如上面的代码中,我们在ClassB里实现了init(num:Int)的重写。这样,即使在ClassB中没有bigNum版本的convenience init(bigNum:Bool),我们依然可以用这个方法来完成子类的初始化

    let anObj = ClassB(bigNum: true)  
    // 输出结果:anObj.numA = 10000, anObj.numB = 10001
    

    总结一下,初始化方法永远遵循下面两条原则

    • 初始化路径必须保证对象完全初始化,这样可以通过调用本类型的designated初始化方法来得到保证;
    • 子类的designated初始化方法必须调用父类的designated方法,以保证父类也完成初始化。

    对于某些我们希望子类中一定实现的designated初始化方法,我们可以通过添加required关键字进行限制,强制子类对这个方法重写实现。这样做的最大好处是可以保证依赖于某个designated初始化方法的convenience一直被调用。

    class ClassAAA {
        let numA: Int
        required init(num: Int) {
            numA = num
        }
        required convenience init(bigNum: Bool) {
            self.init(num: bigNum ? 10000 : 1)
        } }
    class ClassBBB: ClassAAA {
        let numB: Int
        required init(num: Int) {
            numB = num + 1
            super.init(num: num)
        }
    }
    let sencondObj = ClassBB(bigNum: true)
    print(sencondObj.numA, sencondObj.numB)
    
    //输出结果 10000 10001
    

    第一次写,还请码友们多多支持 谢谢!!

    参考

    DESIGNATED,CONVENIENCE 和 REQUIRED

    相关文章

      网友评论

          本文标题:Swift开发--Designated、Convenience和

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