目录
继承
子类
子类指的是在一个已有类的基础上创建一个新的类。
为了指明某个类的超类,将超类名写在子类名的后面,用冒号(:)分隔,语法格式如下:
class SomeClass: SomeSuperclass {
// 类的定义
}
重写属性
- 可以提供定制的 getter(或 setter)来重写任意继承来的属性,无论继承来的属性是存储型的还是计算型的属性。
- 子类并不知道继承来的属性是存储型的还是计算型的,它只知道继承来的属性会有一个名字和类型。在重写一个属性时,必需将它的名字和类型都写出来。
- 注意点:
- 如果你在重写属性中提供了 setter,那么你也一定要提供 getter。
- 如果你不想在重写版本中的 getter 里修改继承来的属性值,你可以直接通过super.someProperty来返回继承来的值,其中someProperty是你要重写的属性的名字。
重写属性观察器
- 可以在属性重写中为一个继承来的属性添加属性观察器。这样一来,当继承来的属性值发生改变时,你就会监测到。
注意:你不可以为继承来的常量存储型属性或继承来的只读计算型属性添加属性观察器。
防止重写
- 可以使用 final 关键字防止它们被重写。
- 如果你写了final方法,属性或下标脚本,在编译时会报错。
- 可以通过在关键字class前添加final特性(final class)来将整个类标记为 final 的,这样的类是不可被继承的,否则会报编译错误。
构造过程
- 构造过程是为了使用某个类、结构体或枚举类型的实例而进行的准备过程。这个过程包含了为实例中的每个属性设置初始值和为其执行必要的准备和初始化任务。
- Swift 构造函数使用 init() 方法。
- 与 Objective-C 中的构造器不同,Swift 的构造器无需返回值,它们的主要任务是保证新实例在第一次使用前完成正确的初始化。
- 类实例也可以通过定义析构器(deinitializer)在类实例释放之前执行清理内存的工作。
存储型属性的初始赋值
- 类和结构体在实例创建时,必须为所有存储型属性设置合适的初始值。
- 存储属性在构造器中赋值时,它们的值是被直接设置的,不会触发任何属性观测器。
- 存储属性在构造器中赋值流程:
- 创建初始值。
- 在属性定义中指定默认属性值。
- 初始化实例,并调用 init() 方法。
内部和外部参数名
-
跟函数和方法参数相同,构造参数也存在一个在构造器内部使用的参数名字和一个在调用构造器时使用的外部参数名字。
-
然而,构造器并不像函数和方法那样在括号前有一个可辨别的名字。所以在调用构造器时,主要通过构造器中的参数名和类型来确定需要调用的构造器。
-
如果你在定义构造器时没有提供参数的外部名字,Swift 会为每个构造器的参数自动生成一个跟内部名字相同的外部名。
-
如果不为构造器的某个参数提供外部名字,可以使用下划线_来显示描述它的外部名。
可选属性类型
- 如果你定制的类型包含一个逻辑上允许取值为空的存储型属性,你都需要将它定义为可选类型optional type(可选属性类型)。
- 当存储属性声明为可选时,将自动初始化为空 nil。
构造过程中修改常量属性
- 只要在构造过程结束前常量的值能确定,你可以在构造过程中的任意时间点修改常量属性的值。
- 对某个类实例来说,它的常量属性只能在定义它的类的构造过程中修改;不能在子类中修改。
默认构造器
- 默认构造器将简单的创建一个所有属性值都设置为默认值的实例
结构体的逐一成员构造器
- 如果结构体对所有存储型属性提供了默认值且自身没有提供定制的构造器,它们能自动获得一个逐一成员构造器。
- 我们在调用逐一成员构造器时,通过与成员属性名相同的参数名进行传值来完成对成员属性的初始赋值。
值类型的构造器代理
构造器可以通过调用其它构造器来完成实例的部分构造过程。这一过程称为构造器代理,它能减少多个构造器间的代码重复。
构造器代理规则
值类型 | 类类型 |
---|---|
不支持继承,所以构造器代理的过程相对简单,因为它们只能代理给本身提供的其它构造器。 你可以使用self.init在自定义的构造器中引用其它的属于相同值类型的构造器。 | 它可以继承自其它类,这意味着类有责任保证其所有继承的存储型属性在构造时也能正确的初始化。 |
类的继承和构造过程
Swift 提供了两种类型的类构造器来确保所有类实例中存储型属性都能获得初始值,它们分别是指定构造器和便利构造器。
指定构造器 | 便利构造器 |
---|---|
类中最主要的构造器 | 类中比较次要的、辅助型的构造器 |
初始化类中提供的所有属性,并根据父类链往上调用父类的构造器来实现父类的初始化。 | 可以定义便利构造器来调用同一个类中的指定构造器,并为其参数提供默认值。你也可以定义便利构造器来创建一个特殊用途或特定输入的实例。 |
每一个类都必须拥有至少一个指定构造器 | 只在必要的时候为类提供便利构造器 |
Init(parameters) { statements } | convenience init(parameters) { statements } |
构造器的继承和重载
- Swift 中的子类不会默认继承父类的构造器。
- 父类的构造器仅在确定和安全的情况下被继承。
- 当你重写一个父类指定构造器时,你需要写override修饰符。
类的可失败构造器
如果一个类,结构体或枚举类型的对象,在构造自身的过程中有可能失败,则为其定义一个可失败构造器。
变量初始化失败可能的原因有:
- 传入无效的参数值。
- 缺少某种所需的外部资源。
- 没有满足特定条件。
为了妥善处理这种构造过程中可能会失败的情况。可以在一个类,结构体或是枚举类型的定义中,添加一个或多个可失败构造器。其语法为在init关键字后面加添问号(init?)。
- 值类型(如结构体或枚举类型)的可失败构造器,对何时何地触发构造失败这个行为没有任何的限制。
- 类的可失败构造器只能在所有的类属性被初始化后和所有类之间的构造器之间的代理调用发生完后触发失败行为。
覆盖一个可失败构造器
- 可以用子类的可失败构造器覆盖基类的可失败构造器。
- 可以用子类的非可失败构造器覆盖一个基类的可失败构造器。
- 可以用一个非可失败构造器覆盖一个可失败构造器,但反过来却行不通。
- 一个非可失败的构造器永远也不能代理调用一个可失败构造器。
可失败构造器 init!
通常通过在init关键字后添加问号的方式(init?)来定义一个可失败构造器,但也可以使用通过在init后面添加惊叹号的方式来定义一个可失败构造器(init!)。
析构过程
- 在一个类的实例被释放之前,析构函数被立即调用。
- 用关键字deinit来标示析构函数,类似于初始化函数用init来标示。
- 析构函数只适用于类类型。
析构过程原理
- Swift 会自动释放不再需要的实例以释放资源。
- Swift 通过自动引用计数(ARC)处理实例的内存管理。
- 通常当你的实例被释放时不需要手动地去清理。但是,当使用自己的资源时,你可能需要进行一些额外的清理。
语法
在类的定义中,每个类最多只能有一个析构函数。析构函数不带任何参数,在写法上不带括号:
deinit {
// 执行析构过程
}
可选链
可选链(Optional Chaining)是一种可以请求和调用属性、方法和子脚本的过程,用于请求或调用的目标可能为nil。
可选链返回两个值:
- 如果目标有值,调用就会成功,返回该值
- 如果目标为nil,调用将返回nil
多次请求或调用可以被链接成一个链,如果任意一个节点为nil将导致整条链失效。
可选链可替代强制解析
通过在属性、方法、或下标脚本的可选值后面放一个问号(?),即可定义一个可选链。
- 可选链 ‘?’
- 感叹号(!)强制展开方法,属性,下标脚本可选链
- ? 放置于可选值后来调用方法,属性,下标脚本
- ! 放置于可选值后来调用方法,属性,下标脚本来强制展开值
- 当可选为 nil 输出比较友好的错误信息
- 当可选为 nil 时强制展开执行错误
连接多层链接
你可以将多层可选链连接在一起,可以掘取模型内更下层的属性方法和下标脚本。然而多层可选链不能再添加比已经返回的可选值更多的层。
- 如果试图通过可选链获得Int值,不论使用了多少层链接返回的总是Int?。
- 相似的,如果你试图通过可选链获得Int?值,不论使用了多少层链接返回的总是Int?。
对返回可选值的函数进行链接
可以通过可选链接来调用返回可空值的方法,并且可以继续对可选值进行链接。