Swift(二)-类的初始化器

424 阅读3分钟

「这是我参与2022首次更文挑战的第10天,活动详情查看:2022首次更文挑战

在讲初始化器之前我们先来看一段代码:

image.png

一个,一个结构体,同样的成员变量;编译结果,报错,而结构体没有报错;这是因为类编译器默认不会自动提供成员初始化器,而对于结构体来说,编译器会自动提供默认的初始化方法(在我们没有指定自定义初始化器的前提下);

我们需要给自定义一个初始化器:

image.png

接下来,我们主要分析一下的初始化器;

类的初始化器

image.png

在上述代码中,我们给Person类定义了三个初始化器,那么在初始化Person的时候就会有三种方式;

image.png

其中init(_ age: Int, _ name: String)因为提供了所有属性的初始化值,我们称为指定初始化器,而其他的init我们称为便捷初始化器,比如:

image.png

我们在init方法前边使用convenience来标识便捷初始化器

Swift中创建结构体的实例时,必须为所有的存储属性设置一个合适的初始值,所以必须要提供对应的指定初始化器(一般情况下只有一个指定初始化器);同时,我们也可以为当前类提供便捷初始化器,需要注意的是,便捷初始化器必须从相同的类中调用另一个初始化器;

image.png

便捷初始化器中没有调用另一个初始化器将会报错;

初始化器的目的就是确保在访问及其属性的时候,属性都已经被初始化了;

初始化器的规则

初始化器有以下几个规则:

  • 指定初始化器必须保证在向上委托给父类初始化器之前,所在类引入的所有属性都要初始化完成;
  • 指定初始化器必须先向上委托父类初始化器,然后才能为继承的属性设置新值;否则,指定初始化器赋予的新值将会被父类中的初始化器覆盖;如下例子:

image.png

Student继承自Person,那么Student的初始化器必须调用父类的初始化器,并且在调用父类初始化器之前,自己的属性必须初始化完成:

image.png

  • 便捷初始化器必须先委托同类中的其他初始化器,然后再为任意属性赋新值,包括同类中定义的属性。否则,便捷初始化器赋予的新值将会被自己类中其他指定初始化器所覆盖;
  • 初始化器在第一阶段初始化完成之前,不能调用任何实例方法,不能读取任何实例属性的值,也不能引用self作为值;

可失败初始化器

当前因为参数的不合法或者外部条件的不满足,存在初始化失败的情况,这个时候Swift允许提供可失败初始化器;在其中写return nil语句,来表明可失败初始化器在何种情况下会出发初始化失败;

image.png

init?标识其是一个可失败初始化器,当age < 0时,Person无法被初始化;

必要初始化器

我们可以在类的初始化器之前添加required修饰符来标识该初始化器为必要初始化器,这样该类的所有子类都必须要实现该初始化器;

image.png

父类提供了rquired修饰的必要初始化器,子类没有实现该初始化器将会报错;

image.png