首页 理论教育 结构体的初始化方式详解

结构体的初始化方式详解

时间:2023-06-23 理论教育 版权反馈
【摘要】:编译器会强制要求新实例的存储属性有值,如果没有为自定义结构体提供初始化方法,就必须通过默认值或成员初始化方法提供必要的值。结构体的默认成员初始化方法很有用,因为这是Swift自动提供的,不需要开发者自己写代码实现。结构体的这个优势让它变得极具吸引力,但不管怎么样,很多时候我们也需要自定义类型的初始化方法。结果与之前一致,说明读者自己实现的初始化方法与编译器提供的行为一致。

结构体的初始化方式详解

结构体既可以有默认初始化方法,也可以有自定义初始化方法。在使用结构体时,通常可以利用默认初始化方法,不过有些场景需要自定义初始化过程。读者可以查看之前的代码,在创建Person和Student的实例时,代码中给属性设置了默认值,实际上是用了Swift编译器提供的空初始化方法(empty initializer,没有参数的初始化方法)。当我们输入代码var personA = Person()时,就用到了空初始化方法并为新实例的属性指定了默认值。默认初始化方法还有一种形式,称作成员初始化方法(memberwise initializer)。对于类型的每个存储属性,成员初始化方法都有相应的参数。在这种情况下,不需要让编译器给新实例的属性设置默认值,而是利用自带的成员初始化方法为所有需要值的属性提供参数。因此读者要理解的是:初始化方法的基本目的是为类型的所有存储属性赋值,保证新的实例可用。编译器会强制要求新实例的存储属性有值,如果没有为自定义结构体提供初始化方法,就必须通过默认值或成员初始化方法提供必要的值。新建Tyre结构体,代码示例如下:

动手写7.5.3 InitPractise->Tyre.swift

回到main.swift中,用Tyre的成员初始化方法初始化一个Tyre实例:

回到main.swift中,用Tyre的成员初始化方法初始化一个Tyre实例:

控制台输出如下:

控制台输出如下:

使用成员初始化方法,成功地给Tyre实例中的属性赋上了值。属性名在调用初始化方法时被用作外部参数名,Swift自动为每个初始化方法的每个参数提供外部参数名。这个约定很重要,因为Swift的初始化方法名字都是init,因此函数名无法用来表示要调用的是哪个特定的初始化方法。参数名及其类型能帮助编译器区分不同的初始化方法,以便知道该调用哪个。

结构体的默认成员初始化方法很有用,因为这是Swift自动提供的,不需要开发者自己写代码实现。结构体的这个优势让它变得极具吸引力,但不管怎么样,很多时候我们也需要自定义类型的初始化方法。下面就来学习如何自定义初始化方法,代码如下:

使用成员初始化方法,成功地给Tyre实例中的属性赋上了值。属性名在调用初始化方法时被用作外部参数名,Swift自动为每个初始化方法的每个参数提供外部参数名。这个约定很重要,因为Swift的初始化方法名字都是init,因此函数名无法用来表示要调用的是哪个特定的初始化方法。参数名及其类型能帮助编译器区分不同的初始化方法,以便知道该调用哪个。

结构体的默认成员初始化方法很有用,因为这是Swift自动提供的,不需要开发者自己写代码实现。结构体的这个优势让它变得极具吸引力,但不管怎么样,很多时候我们也需要自定义类型的初始化方法。下面就来学习如何自定义初始化方法,代码如下:

首先我们要意识到:只要自定义了初始化方法,编译器就不会提供刚才所说的成员初始化方法,所有初始化的任务就交给开发者了,此时开发者就肩负了更大的责任。

这里先覆写了init方法,并设置了两个传参,一个color一个tyreSize。当这段代码编写完之后,编译器就立即报错了。之前使用的成员初始化方法就会有问题,现在需要把传入参数size变成tyreSize,然后编译器则恢复正常,代码如下:(www.xing528.com)

首先我们要意识到:只要自定义了初始化方法,编译器就不会提供刚才所说的成员初始化方法,所有初始化的任务就交给开发者了,此时开发者就肩负了更大的责任。

这里先覆写了init方法,并设置了两个传参,一个color一个tyreSize。当这段代码编写完之后,编译器就立即报错了。之前使用的成员初始化方法就会有问题,现在需要把传入参数size变成tyreSize,然后编译器则恢复正常,代码如下:

color和tyreSize对应的是Tyre里的两个属性,读者可以把参数中的值传递给属性,比如传递给color参数的值被赋给了color属性。因为初始化方法中的参数名和属性名一样,所以访问属性需要明确指定self。tyreSize没有这个问题,所以只需要把初始化方法的tyreSize参数赋给size属性就可以了。

有一个小细节需要读者注意:如果属性是一个常量,在初始化阶段是有机会给常量进行赋值的,这是Swift编译器允许的。这和初始化的目的是一致的,就是确保类型中的属性在初始化完之后都有值。

在这一节中,读者可能已经注意到了一点:Xcode中的Issue Navigator经常会提示发生了一个错误,比如之前使用的初始化方法传参不对,以及没有默认值或者其他一些编译时产生的错误。最后再次运行代码,控制台输出如下:

color和tyreSize对应的是Tyre里的两个属性,读者可以把参数中的值传递给属性,比如传递给color参数的值被赋给了color属性。因为初始化方法中的参数名和属性名一样,所以访问属性需要明确指定self。tyreSize没有这个问题,所以只需要把初始化方法的tyreSize参数赋给size属性就可以了。

有一个小细节需要读者注意:如果属性是一个常量,在初始化阶段是有机会给常量进行赋值的,这是Swift编译器允许的。这和初始化的目的是一致的,就是确保类型中的属性在初始化完之后都有值。

在这一节中,读者可能已经注意到了一点:Xcode中的Issue Navigator经常会提示发生了一个错误,比如之前使用的初始化方法传参不对,以及没有默认值或者其他一些编译时产生的错误。最后再次运行代码,控制台输出如下:

结果与之前一致,说明读者自己实现的初始化方法与编译器提供的行为一致。

结果与之前一致,说明读者自己实现的初始化方法与编译器提供的行为一致。

免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。

我要反馈