@ -14,32 +14,33 @@ Swift 语言存在两种类型:命名型类型和复合型类型。*命名型
> 类型语法
> 类型语法
>
>
> *类型* → [*数组 类型* ](#array -type)
> *类型* → [函数 类型](#function -type)
>
>
> *类型* → [*字典 类型* ](#diction ary-type)
> *类型* → [数组 类型](#arra y-type)
>
>
> *类型* → [*函数 类型* ](#fun ction-type)
> *类型* → [字典 类型](#di ctionary -type)
>
>
> *类型* → [* 类型标识* ](#type-identifier)
> *类型* → [类型标识](#type-identifier)
>
>
> *类型* → [* 元组类型* ](#tuple-type)
> *类型* → [元组类型](#tuple-type)
>
>
> *类型* → [* 可选类型* ](#optional-type)
> *类型* → [可选类型](#optional-type)
>
>
> *类型* → [* 隐式解析可选类型* ](#implicitly-unwrapped-optional-type)
> *类型* → [隐式解析可选类型](#implicitly-unwrapped-optional-type)
>
>
> *类型* → [* 协议合成类型* ](#protocol-composition-type)
> *类型* → [协议合成类型](#protocol-composition-type)
>
>
> *类型* → [*元型 类型* ](#metatyp e-type)
> *类型* →[不透明 类型](#opaqu e-type)
>
>
> *类型* → **任意类型**
> *类型* → [元型类型](#metatype-type)
>
>
> *类型* → ** 自身类型**
> *类型* → [ 自身类型](#self-type)
>
>
> *类型* → [*(类型)*](#type)
> *类型* → **Any**
>
>
> *类型* → **( ** [类型](#type) **) **
## 类型注解 {#type-annotation}
## 类型注解
*类型注解*显式地指定一个变量或表达式的类型。类型注解始于冒号 `:` 终于类型,比如下面两个例子:
*类型注解*显式地指定一个变量或表达式的类型。类型注解始于冒号 `:` 终于类型,比如下面两个例子:
```swift
```swift
@ -56,10 +57,9 @@ func someFunction(a: Int) { /* ... */ }
#### type-annotation {#type-annotation}
#### type-annotation {#type-annotation}
> *类型注解* → **:** [*特性列表*](./07_Attributes.md#attributes)<sub>可选</sub> **输入输出参数**<sub>可选</sub> [*类型*](#type)
> *类型注解* → **:** [*特性列表*](./07_Attributes.md#attributes)<sub>可选</sub> **输入输出参数**<sub>可选</sub> [*类型*](#type)
>
## 类型标识符 {#type-identifier}
## 类型标识符
类型标识符引用命名型类型,还可引用命名型或复合型类型的别名。
* 类型标识符* 引用命名型类型,还可引用命名型或复合型类型的别名。
大多数情况下,类型标识符引用的是与之同名的命名型类型。例如类型标识符 `Int` 引用命名型类型 `Int` ,同样,类型标识符 `Dictionary<String, Int>` 引用命名型类型 `Dictionary<String, Int>` 。
大多数情况下,类型标识符引用的是与之同名的命名型类型。例如类型标识符 `Int` 引用命名型类型 `Int` ,同样,类型标识符 `Dictionary<String, Int>` 引用命名型类型 `Dictionary<String, Int>` 。
@ -85,10 +85,9 @@ var someValue: ExampleModule.MyType
#### type-name {#type-name}
#### type-name {#type-name}
> *类型名称* → [*标识符*](./02_Lexical_Structure.md#identifier)
> *类型名称* → [*标识符*](./02_Lexical_Structure.md#identifier)
>
## 元组类型 {#tuple-type}
## 元组类型
元组类型是使用括号括起来的零个或多个类型,类型间用逗号隔开。
* 元组类型* 是使用括号括起来的零个或多个类型,类型间用逗号隔开。
你可以使用元组类型作为一个函数的返回类型,这样就可以使函数返回多个值。你也可以命名元组类型中的元素,然后用这些名字来引用每个元素的值。元素的名字由一个标识符紧跟一个冒号 `(:)` 组成。[函数和多返回值 ](../chapter2/06_Functions.md#functions_with_multiple_return_values ) 章节里有一个展示上述特性的例子。
你可以使用元组类型作为一个函数的返回类型,这样就可以使函数返回多个值。你也可以命名元组类型中的元素,然后用这些名字来引用每个元素的值。元素的名字由一个标识符紧跟一个冒号 `(:)` 组成。[函数和多返回值 ](../chapter2/06_Functions.md#functions_with_multiple_return_values ) 章节里有一个展示上述特性的例子。
@ -122,8 +121,8 @@ someTuple = (left: 5, right: 5) // 错误:命名类型不匹配
> *元素名* → [*标识符*](./02_Lexical_Structure.md#identifier)
> *元素名* → [*标识符*](./02_Lexical_Structure.md#identifier)
>
>
## 函数类型 {#function-type}
## 函数类型
函数类型表示一个函数、方法或闭包的类型,它由参数类型和返回值类型组成,中间用箭头(`->` )隔开:
* 函数类型* 表示一个函数、方法或闭包的类型,它由参数类型和返回值类型组成,中间用箭头(`->` )隔开:
> ( `参数类型`) ->( `返回值类型`)
> ( `参数类型`) ->( `返回值类型`)
@ -219,7 +218,7 @@ func takesTwoFunctions(first: (Any) -> Void, second: (Any) -> Void) {
> *参数标签* → [*标识符*](./02_Lexical_Structure.md#identifier)
> *参数标签* → [*标识符*](./02_Lexical_Structure.md#identifier)
>
>
## 数组类型 {#array-type}
## 数组类型
Swift 语言为标准库中定义的 `Array<Element>` 类型提供了如下语法糖:
Swift 语言为标准库中定义的 `Array<Element>` 类型提供了如下语法糖:
> [`类型`]
> [`类型`]
@ -251,7 +250,7 @@ var array3D: [[[Int]]] = [[[1, 2], [3, 4]], [[5, 6], [7, 8]]]
> *数组类型* → **[** [*类型*](#type) **]**
> *数组类型* → **[** [*类型*](#type) **]**
>
>
## 字典类型 {#dictionary-type}
## 字典类型
Swift 语言为标准库中定义的 `Dictionary<Key, Value>` 类型提供了如下语法糖:
Swift 语言为标准库中定义的 `Dictionary<Key, Value>` 类型提供了如下语法糖:
> [`键类型` : `值类型`]
> [`键类型` : `值类型`]
@ -279,7 +278,7 @@ let someDictionary: Dictionary<String, Int> = ["Alex": 31, "Paul": 39]
> *字典类型* → **[** [*类型*](#type) **:** [*类型*](#type) **]**
> *字典类型* → **[** [*类型*](#type) **:** [*类型*](#type) **]**
>
>
## 可选类型 {#optional-type}
## 可选类型
Swift 定义后缀 `?` 来作为标准库中定义的命名型类型 `Optional<Wrapped>` 的语法糖。换句话说,下面两个声明是等价的:
Swift 定义后缀 `?` 来作为标准库中定义的命名型类型 `Optional<Wrapped>` 的语法糖。换句话说,下面两个声明是等价的:
```swift
```swift
@ -346,13 +345,12 @@ let implicitlyUnwrappedArray: [Int]! // 正确
> *隐式解析可选类型* → [*类型*](#type) **!**
> *隐式解析可选类型* → [*类型*](#type) **!**
>
>
## 协议合成类型 {#protocol-composition-type}
## 协议合成类型
协议合成类型定义了一种遵循协议列表中每个指定协议的类型,或者一个现有类型的子类并遵循协议列表中每个指定协议。协议合成类型只能用在类型注解、泛型参数子句和泛型 `where` 子句中指定类型。
* 协议合成类型* 定义了一种遵循协议列表中每个指定协议的类型,或者一个现有类型的子类并遵循协议列表中每个指定协议。协议合成类型只能用在类型注解、泛型参数子句和泛型 `where` 子句中指定类型。
协议合成类型的形式如下:
协议合成类型的形式如下:
> `Protocol 1` & `Procotol 2`
> `Protocol 1` & `Procotol 2`
>
协议合成类型允许你指定一个值,其类型遵循多个协议的要求而不需要定义一个新的命名型协议来继承它想要符合的各个协议。比如,协议合成类型 `Protocol A & Protocol B & Protocol C` 等效于一个从 `Protocol A` , `Protocol B` , `Protocol C` 继承而来的新协议。同样的,你可以使用 `SuperClass & ProtocolA` 来取代申明一个新的协议作为 `SuperClass` 的子类并遵循 `ProtocolA` 。
协议合成类型允许你指定一个值,其类型遵循多个协议的要求而不需要定义一个新的命名型协议来继承它想要符合的各个协议。比如,协议合成类型 `Protocol A & Protocol B & Protocol C` 等效于一个从 `Protocol A` , `Protocol B` , `Protocol C` 继承而来的新协议。同样的,你可以使用 `SuperClass & ProtocolA` 来取代申明一个新的协议作为 `SuperClass` 的子类并遵循 `ProtocolA` 。
@ -378,10 +376,34 @@ typealias PQR = PQ & Q & R
#### protocol-composition-continuation {#protocol-composition-continuation}
#### protocol-composition-continuation {#protocol-composition-continuation}
> *协议合成延续* → [*协议标识符*](#protocol-identifier) | [*协议合成类型*](#protocol-composition-type)
> *协议合成延续* → [*协议标识符*](#protocol-identifier) | [*协议合成类型*](#protocol-composition-type)
>
## 元类型 {#metatype-type}
## 不透明类型
元类型是指任意类型的类型,包括类类型、结构体类型、枚举类型和协议类型。
*不透明类型*定义了遵循某个协议或者合成协议的类型,但不需要指明底层的具体类型。
不透明类型可以作为函数或下标的返回值,亦或是属性的类型使用。
不透明类型不能作为元组类型的一部分或范型类型使用,比如数组元素类型或者可选值的包装类型。
不透明类型的形式如下:
> some `constraint`
*constraint* 可以是类类型,协议类型,协议组合类型或者 `Any` 。值只有当它遵循该协议或者组合协议,或者从该类继承的时候,才能作为这个不透明类型的实例使用。和不透明值交互的代码只能使用该值定义在 *constraint* 上的接口。
协议声明里不能包括不透明类型。类不能使用不透明类型作为非 final 方法的返回值。
使用不透明类型作为返回值的函数必须返回单一公用底层类型。返回的类型可以包含函数范型类型参数的一部分。举个例子,函数 `someFunction<T>()` 可以返回类型 `T` 或者 `Dictionary<String,T>` 的值。
> 不透明类型语法
#### opaque-type {#opaque-type}
> *不透明类型* → **some** [type](#type)
## 元类型
*元类型*是指任意类型的类型,包括类类型、结构体类型、枚举类型和协议类型。
类、结构体或枚举类型的元类型是相应的类型名紧跟 `.Type` 。协议类型的元类型——并不是运行时遵循该协议的具体类型——是该协议名字紧跟 `.Protocol` 。比如,类 `SomeClass` 的元类型就是 `SomeClass.Type` ,协议 `SomeProtocol` 的元类型就是 `SomeProtocal.Protocol` 。
类、结构体或枚举类型的元类型是相应的类型名紧跟 `.Type` 。协议类型的元类型——并不是运行时遵循该协议的具体类型——是该协议名字紧跟 `.Protocol` 。比如,类 `SomeClass` 的元类型就是 `SomeClass.Type` ,协议 `SomeProtocol` 的元类型就是 `SomeProtocal.Protocol` 。
@ -428,10 +450,48 @@ let anotherInstance = metatype.init(string: "some string")
#### metatype-type {#metatype-type}
#### metatype-type {#metatype-type}
> *元类型* → [*类型*](#type) **.** **Type** | [*类型*](#type) **.** **Protocol**
> *元类型* → [*类型*](#type) **.** **Type** | [*类型*](#type) **.** **Protocol**
>
## 类型继承子句 {#type-inheritance-clause}
## 自身 类型
类型继承子句被用来指定一个命名型类型继承自哪个类、采纳哪些协议。类型继承子句开始于冒号 `:` ,其后是类型标识符列表。
`Self` 类型不是具体的类型,而是让你更方便的引用当前类型,不需要重复或者知道该类的名字。
在协议声明或者协议成员声明时,`Self` 类型引用的是最终遵循该协议的类型。
在结构体,类或者枚举值声明时,`Self` 类型引用的是声明的类型。在某个类型成员声明时,`Self` 类型引用的是该类型。在类成员声明时,`Self` 可以在方法的返回值和方法体中使用,但不能在其他上下文中使用。举个例子,下面的代码演示了返回值是 `Self` 的实例方法 `f` 。
```swift
class Superclass {
func f () -> Self { return self }
}
let x = Superclass ()
print ( type ( of : x . f ()))
// 打印 "Superclass"
class Subclass : Superclass { }
let y = Subclass ()
print ( type ( of : y . f ()))
// 打印 "Subclass"
let z : Superclass = Subclass ()
print ( type ( of : z . f ()))
// 打印 "Subclass"
```
上面例子的最后一部分表明 `Self` 引用的是值 `z` 的运行时类型 `Subclass` ,而不是变量本身的编译时类型 `Superclass` 。
在嵌套类型声明时,`Self` 类型引用的是最内层声明的类型。
`Self` 类型引用的类型和 Swift 标准库中 [type(of:) ](https://developer.apple.com/documentation/swift/2885064-type ) 函数的结果一样。使用 `Self.someStaticMember` 访问当前类型中的成员和使用 `type(of: self).someStaticMember` 是一样的。
> 自身类型语法
#### self-type{#self-type}
> *自身类型* → **Self**
## 类型继承子句
*类型继承子句*被用来指定一个命名型类型继承自哪个类、采纳哪些协议。类型继承子句开始于冒号 `:` ,其后是类型标识符列表。
类可以继承自单个超类,并遵循任意数量的协议。当定义一个类时,超类的名字必须出现在类型标识符列表首位,然后跟上该类需要遵循的任意数量的协议。如果一个类不是从其它类继承而来,那么列表可以以协议开头。关于类继承更多的讨论和例子,请参阅 [继承 ](../chapter2/13_Inheritance.md )。
类可以继承自单个超类,并遵循任意数量的协议。当定义一个类时,超类的名字必须出现在类型标识符列表首位,然后跟上该类需要遵循的任意数量的协议。如果一个类不是从其它类继承而来,那么列表可以以协议开头。关于类继承更多的讨论和例子,请参阅 [继承 ](../chapter2/13_Inheritance.md )。
@ -450,11 +510,9 @@ let anotherInstance = metatype.init(string: "some string")
> *类型继承列表* → [*类型标识符*](#type-identifier) | [*类型标识符*](#type-identifier) **,** [*类型继承列表*](#type-inheritance-list)
> *类型继承列表* → [*类型标识符*](#type-identifier) | [*类型标识符*](#type-identifier) **,** [*类型继承列表*](#type-inheritance-list)
>
>
#### class-requirement {#class-requirement}
## 类型推断
## 类型推断 {#type-inference}
Swift 广泛使用*类型推断*,从而允许你省略代码中很多变量和表达式的类型或部分类型。比如,对于 `var x: Int = 0` ,你可以完全省略类型而简写成 `var x = 0` ,编译器会正确推断出 `x` 的类型 `Int` 。类似的,当完整的类型可以从上下文推断出来时,你也可以省略类型的一部分。比如,如果你写了 `let dict: Dictionary = ["A" : 1]` ,编译器能推断出 `dict` 的类型是 `Dictionary<String, Int>` 。
Swift 广泛使用类型推断,从而允许你省略代码中很多变量和表达式的类型或部分类型。比如,对于 `var x: Int = 0` ,你可以完全省略类型而简写成 `var x = 0` ,编译器会正确推断出 `x` 的类型 `Int` 。类似的,当完整的类型可以从上下文推断出来时,你也可以省略类型的一部分。比如,如果你写了 `let dict: Dictionary = ["A" : 1]` ,编译器能推断出 `dict` 的类型是 `Dictionary<String, Int>` 。
在上面的两个例子中,类型信息从表达式树的叶子节点传向根节点。也就是说,`var x: Int = 0` 中 `x` 的类型首先根据 `0` 的类型进行推断,然后将该类型信息传递到根节点(变量 `x` )。
在上面的两个例子中,类型信息从表达式树的叶子节点传向根节点。也就是说,`var x: Int = 0` 中 `x` 的类型首先根据 `0` 的类型进行推断,然后将该类型信息传递到根节点(变量 `x` )。