JHHK

欢迎来到我的个人网站
行者常至 为者常成

10_1、初始化器(一)

目录

多态分析

/// 一、多态分析
func PolymorphismAnaly(){
    class Animal{
        func speak () -> Void {
            print("Animal speak")
        }
        
        func eat() -> Void {
            print("Animal eat")
        }
    }
    
    
    class Dog:Animal{
        override func speak() {
            print("Dog speak")
        }
        override func eat() {
            print("Dog eat")
        }
        
        func run() -> Void {
            print("Dog run")
        }
    }
    
    
    var ani:Animal = Animal()
    ani.speak()//Animal speak
    ani.eat()//Animal eat
    
    ani = Dog()
    ani.speak()//Dog speak
    ani.eat()//Dog eat
    
    /**
     多态的实现原理:
     1、OC:Runtime
     2、C++ 虚表(虚函数表)
     Swift中多态的实现原理 类似C++
     */
}

初始化器分类

img

/// 二、初始化器分类
func initializerClass() -> Void {
    
    /**
     类、结构体、枚举都可以定义初始化器
     
     类有2种初始化器:指定初始化器(designated initializer)、便捷初始化器(convenience initializer)
     
     // 指定初始化器
     init(parameters) {
        statements
     }
     
     // 便捷初始化器
     convenience init(parameters) {
        statements
     }
     
     
     每个类至少有一个指定初始化器,指定初始化器是类的主要初始化器
     默认初始化器总是类的指定初始化器
     类偏向于少量指定初始化器,一个类通常只有一个指定初始化器
     
     初始化器的相互调用规则
     指定初始化器必须从它的直系父类调用指定初始化器
     便捷初始化器必须从相同的类里调用另一个初始化器
     便捷初始化器最终必须调用一个指定初始化器
     
     这一套规则保证了:
     使用任意初始化器,都可以完整地初始化实例
     */
    
    
    //1、指定初始化器
    do{
        print("---------1---------")
        class Size{
            var x:Int
            var y:Int
            //下面四个都是类的主要初始化器
            init() {
                x = 0
                y = 0
            }
            
            init(x:Int) {
                self.x = x
                self.y = 0
            }

            init(y:Int) {
                self.x = 0
                self.y = y
            }

            init(x:Int,y:Int) {
                self.x = x
                self.y = y
            }
        }
        
        let s = Size()
        let s1 = Size(x: 10)
        let s2 = Size(y: 10)
        let s3 = Size(x: 10, y: 10)
        print(s.x,s.y)      //0 0
        print(s1.x,s1.y)    //10 0
        print(s2.x,s2.y)    //0 10
        print(s3.x,s3.y)    //10 10
    }
    
    
    //2、便捷初始化器
    do{
        print("---------2---------")
        class Size2{
            var x:Int
            var y:Int
            init(x:Int,y:Int) {
                self.x = x
                self.y = y
            }
            
            //便捷初始化器必须调用一个指定初始化器
            convenience init(){
                //调用指定初始化器需放在首行
                self.init(x:0,y:0)
                self.x = 30
                self.y = 30
            }
            
            convenience init(x:Int){
                self.init(x:x,y:0)
            }
            
            convenience init(y:Int){
                self.init(x:0,y:y)
            }
        }
        
        let si0 = Size2()
        let si1 = Size2(x: 20)
        let si2 = Size2(y: 20)
        let si3 = Size2(x: 20, y: 20)
        print(si0.x,si0.y)//30 30
        print(si1.x,si1.y)//20 0
        print(si2.x,si2.y)//0 20
        print(si3.x,si3.y)//20 20
    }
    
    
    //3、有继承关系的初始化器
    do{
        print("---------3---------")
        
        /**

         Swift在编码安全方面是煞费苦心,为了保证初始化过程的安全,设定了两段式初始化、 安全检查
         
         两段式初始化
             第1阶段:初始化所有存储属性
                 ① 外层调用指定\便捷初始化器
                 ② 分配内存给实例,但未初始化
                 ③ 指定初始化器确保当前类定义的存储属性都初始化
                 ④ 指定初始化器调用父类的初始化器,不断向上调用,形成初始化器链
             
             第2阶段:设置新的存储属性值
                 ① 从顶部初始化器往下,链中的每一个指定初始化器都有机会进一步定制实例
                 ② 初始化器现在能够使用self(访问、修改它的属性,调用它的实例方法等等)
                 ③ 最终,链中任何便捷初始化器都有机会定制实例以及使用self
           
         
         安全检查
             指定初始化器必须保证在调用父类初始化器之前,其所在类定义的所有存储属性都要初始化完成
             指定初始化器必须先调用父类初始化器,然后才能为继承的属性设置新值
             便捷初始化器必须先调用同类中的其它初始化器,然后再为任意属性设置新值
             初始化器在第1阶段初始化完成之前,不能调用任何实例方法、不能读取任何实例属性的值,也不能引用self
             直到第1阶段结束,实例才算完全合法

         */
        
        //父类
        class Person {
            var age:Int
            //指令初始化器,确保当前类的所有存储属性都初始化
            init(age:Int) {
                self.age = age
            }
            
            //便捷初始化器
            convenience init(){
                self.init(age:0)
            }
        }
        
        
        class Student : Person {
            var scrore:Int
            init(age:Int,scrore:Int) {
                //以下是第一阶段:初始化所有的存储属性
                self.scrore = scrore
                //必须调用父类的指定初始化器,必须放在自己的属性初始化之后
                //self.age = 10//报错:'self' used in property access 'age' before 'super.init' call
                super.init(age:age)
                
                
                //以下是第二阶段:设置新的值
                self.age = 18
            }
            
            
            init(scrore: Int) {
                self.scrore = scrore
                super.init(age:0)
            }
            
            /**
             当重写父类的指定初始化器时,必须加上override(即使子类的实现是便捷初始化器)
             如果子类写了一个匹配父类便捷初始化器的初始化器,不用加上override
             因为父类的便捷初始化器永远不会通过子类直接调用,因此,严格来说,子类无法重写父类的便捷初始化器
             */
            override init(age:Int){
                self.scrore = 0
                super.init(age: age)
            }
//            convenience override  init(age:Int){
//                self.init(age:age,scrore:0)
//            }
            
            /**
             如果子类写了一个匹配父类便捷初始化器的初始化器,不用加上override
             因为父类的便捷初始化器永远不会通过子类直接调用,因此,严格来说,子类无法重写父类的便捷初始化器
             */
            convenience init() {
                self.init(age:18,scrore:98)
            }
        }
        
        let stu = Student()
        print(stu.scrore,stu.age)//98 18
    }
}

初始化器使用注意

/// 三、初始化器使用注意
func initializerUse() -> Void {
    
    //1、使用举例
    do{
        class Person {
            var age:Int = 0
            var height:Int = 180
            
            init(age:Int,height:Int){
                self.age = age
                self.height = height
            }
            
            convenience init(age:Int){
                self.init(age:age,height:0)
            }
            
            convenience init(height:Int){
                self.init(age:0,height:height)
            }
            
            convenience init(){
                self.init(age:0,height:0)
            }
        }
        
        let p = Person()
        print(p.age,p.height)//0 0
    }
    
    
    //2、使用注意
    do{
        class Person{
            var age:Int
            init(age:Int) {
                self.age = age
            }
            
            //便捷初始化器用于:方便本类初始化调用、其它便捷初始化器内调用
            //子类在有自定义初始化器的情况下无法调用
            
            /**
             便捷初始化器用于:
                 方便本类初始化调用
                 其它便捷初始化器内调用
                 子类若无init()方法,子类会调用,若有init()初始化器的情况下无法调用
             */
            convenience init(){
                print("Person init()")
                self.init(age:0)
            }
        }
        
        
        class Student:Person{
            var score:Int
            init(score:Int){
                self.score = score
                super.init(age:0)
            }
            
            //指定初始化器 与 父类的 便捷初始化器 方法名相同
            //不会冲突 不需要加override 也不是重写
            init(){
                print("Student init()")
                self.score = 0
                super.init(age:0)
            }
            
            
            override init(age: Int) {
                self.score = 0
                super.init(age: age)
            }
        }
        
        let stu1 = Student(age:0)
        print(stu1)
        
        let stu2 = Student()//Student init()
        print(stu2)
    }
}

自动继承初始化器

///四、自动继承初始化器
func autoInitializer() -> Void {
    class Person{
        var age:Int = 0
        var name:NSString = ""
        init(age:Int,name:NSString){
            self.age = age
            self.name = name
        }
        
        convenience init(age:Int) {
            self.init(age:age,name:"")
        }

        convenience init(name:NSString){
            self.init(age:0,name:name)
        }
    }
    
    class Student:Person{
        //有自定义的指定初始化器 就无法自动继承
        //没有自定义的指定初始化器 就可以继承父类所有的指定初始化器和便捷初始化器
//        init(){
//
//        }
        
        //重写父类所有的指定初始化器也可以达到跟没有自定义初始化器相同的效果
//        override init(age: Int, name: NSString) {
//            super.init(age: age,name:name)
//        }
        
        //将父类的所有指定初始化器重写成便捷初始化器也能达到相同效果
//        override convenience init(age: Int, name: NSString) {
//            self.init(age:age)
//        }
        
        //添加便捷初始化器不影响继承
        convenience init(){
            self.init(age:0,name:"")
        }
    }
    
    
    let stu0 = Student(age: 0)
    let stu1 = Student(name: "Jack")
    let stu2 = Student(age: 0, name: "jack")
    let stu3 = Student()//便捷初始化器可以调用 且便捷初始化器内的指定初始化器来自自动继承
    print(stu0,stu1,stu2,stu3)
}

行者常至,为者常成!





R
Valine - A simple comment system based on Leancloud.