「这是我参与2022首次更文挑战的第10天,活动详情查看:2022首次更文挑战」
在讲初始化器之前我们先来看一段代码:
一个类,一个结构体,同样的成员变量;编译结果,类报错,而结构体没有报错;这是因为类编译器默认不会自动提供成员初始化器,而对于结构体来说,编译器会自动提供默认的初始化方法(在我们没有指定自定义初始化器的前提下);
我们需要给类自定义一个初始化器:
接下来,我们主要分析一下类的初始化器;
类的初始化器
在上述代码中,我们给Person类定义了三个初始化器,那么在初始化Person的时候就会有三种方式;
其中init(_ age: Int, _ name: String)因为提供了所有属性的初始化值,我们称为指定初始化器,而其他的init我们称为便捷初始化器,比如:
我们在init方法前边使用convenience来标识便捷初始化器;
在Swift中创建类和结构体的实例时,必须为所有的存储属性设置一个合适的初始值,所以必须要提供对应的指定初始化器(一般情况下只有一个指定初始化器);同时,我们也可以为当前类提供便捷初始化器,需要注意的是,便捷初始化器必须从相同的类中调用另一个初始化器;
便捷初始化器中没有调用另一个初始化器将会报错;
初始化器的目的就是确保在访问
类及其属性的时候,类和属性都已经被初始化了;
初始化器的规则
初始化器有以下几个规则:
指定初始化器必须保证在向上委托给父类初始化器之前,所在类引入的所有属性都要初始化完成;指定初始化器必须先向上委托父类初始化器,然后才能为继承的属性设置新值;否则,指定初始化器赋予的新值将会被父类中的初始化器覆盖;如下例子:
Student继承自Person,那么Student的初始化器必须调用父类的初始化器,并且在调用父类初始化器之前,自己的属性必须初始化完成:
便捷初始化器必须先委托同类中的其他初始化器,然后再为任意属性赋新值,包括同类中定义的属性。否则,便捷初始化器赋予的新值将会被自己类中其他指定初始化器所覆盖;初始化器在第一阶段初始化完成之前,不能调用任何实例方法,不能读取任何实例属性的值,也不能引用self作为值;
可失败初始化器
当前因为参数的不合法或者外部条件的不满足,存在初始化失败的情况,这个时候Swift允许提供可失败初始化器;在其中写return nil语句,来表明可失败初始化器在何种情况下会出发初始化失败;
init?标识其是一个可失败初始化器,当age < 0时,Person无法被初始化;
必要初始化器
我们可以在类的初始化器之前添加required修饰符来标识该初始化器为必要初始化器,这样该类的所有子类都必须要实现该初始化器;
父类提供了rquired修饰的必要初始化器,子类没有实现该初始化器将会报错;