十四.构造器
1.构造器用于完成实例的构造过程。这个过程包括为实例中的每个存储属性设置初始值和执行必要的准备和初始化任务。
2. Swift的构造器本质上就是一个或多个名为init的函数(不允许使用func关键字)
3.构造器的主要作用就是完成实例中每个类、结构体中实例存储属性(枚举不能定义实例存储属性)的初始化。为实例存储属性赋初始值有两个时机:定义实例存储属性时指定初始值;在构造器中为实例存储属性指定初始值。
4.如果程序定义实例存储属性时指定了初始值,或者在构造器中为实例存储属性分配了初始值,那么都不会触发该属性的属性观察者。
5.构造器的外部形参名与函数的外部形参名是不同的。函数的形参默认是没有外部形参名的,如果想为函数的形参指定外部形参名,有如下两种方式:
(1)在局部形参名前显式定义一个外部形参名
(2)在局部形参名前添加#前缀,让外部形参名与局部形参名相同。
6. S为他默认为构造器的所有前缀都添加了外部形参名:外部形参名与局部形参名相同----就像在局部形参名前添加了#前缀一样。
7.如果希望外部形参名与内部形参名不同,Swift也允许为构造器形参显式地指定外部形参名。
8.如果希望取消隐式的外部形参名(不需要任何外部形参名),Swift允许通过将外部形参名指定为下划线来取消隐式的外部形参名。
9.在构造过程中常量属性是可修改的:与普通常量不同的是:在结构体或类中使用let声明的常量可以在构造过程中被修改,而且允许多次被修改。这是因为let声明的常量表示在它被初始化后不能被重新赋值,但结构体或类的构造器的整个构造过程都属于对常量执行初始化,因此Swift允许在构造过程中对let声明的常量多次赋值。
10.如果某个存储属性的默认值需要特别的计算或定制,此时程序可通过闭包或全局函数(不能通过调用实例方法)为该属性指定初始值。每当程序创建该类型的实例时,对应的闭包或者函数就会执行,它们的返回值将作为该存储属性的初始值。
11.用于作为存储属性初始值的函数或闭包的返回值类型需要与该属性的类型匹配。
12.使用闭包或函数对存储属性赋初始值时,不能在闭包中访问该结构体或类的其他实例存储属性(即使它们有初始值),不能使用self,也不能调用其他实例方法----这是因为闭包本身会在构造阶段执行,此时该实例的其他部分还没有完成初始化。
13.函数的重载同样适用于构造器(构造器就是一种特殊的函数)当一个类型中包含多个构造器(构造器必须同名),且多个构造器的形参列表不同(包括形参个数或者形参类型),或者形参的外部形参名不通过时,都可以算是构造器重载。
14.如果构造器B中完全包含了构造器A。对于这种完全包含的情况,可以在定义构造器时,通过self.init(实参)调用其他构造器来完成实例的部分构造过程,这种方式呗称为构造器代理。结构体和类的构造器代理方式并不同。
十五.可能失败的构造器
1.有些时候,枚举、结构体、类的构造器可能不会成功地返回该类型的实例,比如用户传入的构造器参数无效,或者对构造器过程所需要的外部资源缺失等等情况,此时,Swift允许定义“可能失败的构造器”
2.可能失败的构造器使用init?或init!关键字进行定义,在这种构造器的执行体内使用return nil来表示构造失败,该构造器返回了一个nil(空值)。其中init?构造器返回一个可选类型的实例,因此程序必须对init?构造器返回的实例进行强制解析;而init!构造器返回一个隐式可选类型的实例,因此程序可对init!构造器返回实例进行隐式解析。
3.结构体与可能失败的构造器----举个栗子:
struct Cat
{
let name : String
init?(name : String)
{
if name.isEmpty{
return nil
}
self.name = name
}
}
4.枚举与可能失败的构造器:由于枚举不允许随意地创建实例(枚举的实例应该是固定的)因此可能失败的构造器用处更广,这种构造器可根据程序传入的构造器参数选择枚举成员,如果对应的构造器参数无法确定对应的枚举成员,则返回nil。
15.举个栗子:
enum Season
{
case Spring, Summer, Autumn, Winter
//使用init!定义可能失败的构造器,则该构造器创建的实例可进行隐士解析
init!(name : Character){
switch name{
case "S","s":
self = .Spring
case "U","u":
self = .Summer
case "A","a":
self = .Autumn
case "W","w":
self = .Winter
default:
return nil
}
}
}
let s1 = Season(name : "s")
if s1 != nil
{
print("Season实例构造成功")
}
let s2 = Season(name : "x")
print(s2 == nil)
从上面可以看出,枚举的init!构造器将会根据传入的参数选择对应的枚举成员,该构造器并没有创建新的Season实例(枚举也不允许随意地创建实例),该构造器只是根据传入参数选择对应的枚举成员,并将该成员赋值给self;当传入的参数找不到对应的枚举成员时,构造失败,该构造器返回nil。
16.实际上,对于带由于原始值的枚举,Swift默认提供了一个init?(rawValue:)构造器,如果用户传入的原始值能找到对应的枚举成员,该构造器将会返回对应的枚举值;如果用户传入的原始值找不到对应的成员,该构造器将会返回nil,代表构造失败。
网友评论