美文网首页Swift 从入门到放弃
swift5基本语法-初始化器

swift5基本语法-初始化器

作者: 翀鹰精灵 | 来源:发表于2021-05-02 21:30 被阅读0次

在swift中,类class、结构体struct、枚举enum 都可以定义初始化器。实际开发中枚举自定义初始化用的比较少,枚举定义类型单一,下面主要讲解下类class初始化用法。

枚举常规用法如下:

enum Season :Int {
    case spring
    case summer
    case autumn
    case winter
}
Season.spring

结构体常规用法如下:

struct Size {
    init(x: Int,y:Int) {
      print("x=\(x) ,y=\(y)")
    }
}

var p = Size(x: 10,y: 20)

class初始化器有两种:
  • 1. 指定初始化器(designated Initializer)
  • 2. 便捷初始化器(convenience initializer)
  • ① 指定初始化器
   /// 指定初始化器
   init(parameters) {
     statements
   }
  • ② 便捷初始化器
   /// 便捷初始化器
   convenience init(parameters) {
     statements
   }

注意:

  • 每个类至少有一个指定初始化器,指定初始化器是类的主要初始化器,
  • 每个类会默认生成init() {} 格式的默认初始化器;
  • 可以自定义init(x:Int,y:Int) {}格式指定化初始化器
  • 便捷初始化器convenience关键词开头,且内部必须调用指定初始化器self.init()
两种初始化器写法示例如下:

一、指定初始化器

class Point {
    var x : Int = 0
    var y : Int = 0
    init(x:Int,y:Int) {
        self.x = x
        self.y = y
    }
}

let p = Point(x: 10, y: 10)

二、便捷初始化器

class Point {
    var x : Int = 0
    var y : Int = 0

    convenience init(x:Int,y:Int) {
        //一定要调用,否则会报错
        self.init()
        self.x = x
        self.y = y
    }
}

let p = Point(x: 10, y: 10)
初始器相互调用规则:
  • 规则1:
01.png

便捷初始化器最终必须调用同一个指定初始化器

小结:
便捷初始化器一般是为了提供便捷的创建对象的方法,比如一个Point对象,他的指定初始化器(主要初始化器)init(x:Int,y:Int) {}方法,但是有时候我们只想设值x, 暂时不想赋值y, y只想后续再赋值,那么此时我们可以通过便捷初始化器提供一个convenience init(x:Int) {}的创建方法。
此时,再次创建Point对象的时候,就会有该构建方法的提示,如下图所示:

02.png

可能有的人会反驳,说可以提供多个初始化方法,下图所示:

03.png

但是这种可能会有一个不好的方法,比如我们的init(x:Int,y:Int) {}指定初始化器(主要初始化器)里面可能不仅仅是赋值的操作,还会有一些其它的逻辑,所以我们创建这个Point 对象的时候需要执行init(x:Int,y:Int) {}初始化方法。

比如,不管什么初始化方法,我们都要执行init(x:Int,y:Int) {}指定初始化器(主要初始化器)里面的方法,便捷初始化器convenience init(x:Int) {}就是一个很好的选择。便捷初始化器也就是为了方便开发者创建这个对象而提供的方法,直白的说也就是附带创建对象的方法,适合便捷初始化器。

便捷初始化器都会调用init(x:Int,y:Int) {}指定初始化器的,所以这种构建方法比开发者自己提供多个初始化方法更加安全。

总结:
①. 一般把我们会把我们认为最主要的对象初始化方法定义为init() {}指定初始化器(主要初始化器)
②. 其它附带的创建方法,间接调用指定初始化器的我们把它设置为便捷初始化器

  • 规则2:
  • 指定初始化器(主要初始化器)必须从相同的类里调用另一个初始化器

如下面的代码就会提示报错:

04.png

正确的代码应该如下所示:

05.png
注意:
这里报错,主要是因为不可以直接访问父类的age,因为这里有个规则:
指定初始化器必须调用它直系父类的指定初始化器;
因为指定初始化器是我们创建这个类必须要执行的步骤;
如果子类的指定初始化器不调用父类的指定初始化器的话,那么父类的初始化方法可能就无法执行,这样就会产生问题。
顺序:要求需要先把自己类的初始化属性赋值完,然后再调用父类初始化器。
疑惑总结:
(1). 指定初始化器不可以调用自己的指定初始化器,必须调用父类的指定初始化器。
06.png 07.png
(2).如果是自己的便捷初始化器,不可以调用父类的指定初始化器,必须调用自己的指定初始化器
08.png 09.png

(3).便捷初试化器可以调用自己的便捷初始化器

(4).指定初始化器(主要初始化器)必须从相同的类里调用另一个初始化器;

苹果初始化器相互调佣示意图:

010.png

Swift 初始化器的安全检查

  • 指定初始化器必须保证再调用父类初始化器之前,其所在类定义的所有存储属性都要初始化完成;
  • 指定初始化器必须先调用父类初始化器,然后才能为继承的属性设置新值;
  • 便捷初始化器必须先调用同类中的其它初始化器,然后再为任意属性设置新值;
三、重写初始化器

开发中我们也会涉及到重写,但是一般都是加override 关键字重写方法,重写初始化器一般都是用在类继承里面,比如Student 继承Person 类,但是都有同一个 init(age:Int,score:Int)初始化方法(参数个数,参数类型,参数标签名称完全一模一样),这种就是重写,如下所示:

011.png
总结:
  • 当重写父类的指定初始化器时,必须加上override (即使子类的实现是便捷初始化器)
  • 如果子类写了一个和父类一样的便捷初始化器,不用加override,因为这种情况严格意义上不算是重写;
013.png

因为上述这段代码所示意的情况,便捷初始化器只能被父类自己调用,不可能被子类调用,所以子类无法重写父类的便捷初始化器。

四、自动继承
  • 如果子类没有自定义任何指定初始化器,它会自动继承父类所有的指定初始化器;
014.png
至此,初始化器的学习记录到这里,方便后续查阅。

END.

相关文章

网友评论

    本文标题:swift5基本语法-初始化器

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