新版
This commit is contained in:
123
source/chapter3/03_Types.md
Executable file → Normal file
123
source/chapter3/03_Types.md
Executable file → Normal file
@ -18,16 +18,16 @@
|
|||||||
- [类型继承子句(Type Inheritance Clause)](#type_inheritance_clause)
|
- [类型继承子句(Type Inheritance Clause)](#type_inheritance_clause)
|
||||||
- [类型推断(Type Inference)](#type_inference)
|
- [类型推断(Type Inference)](#type_inference)
|
||||||
|
|
||||||
Swift 语言存在两种类型:命名型类型和复合型类型。*命名型类型*是指定义时可以给定名字的类型。命名型类型包括类、结构体、枚举和协议。比如,一个用户定义的类`MyClass`的实例拥有类型`MyClass`。除了用户定义的命名型类型,Swift 标准库也定义了很多常用的命名型类型,包括那些表示数组、字典和可选值的类型。
|
Swift 语言存在两种类型:命名型类型和复合型类型。命名型类型是指定义时可以给定名字的类型。命名型类型包括类、结构体、枚举和协议。比如,一个用户定义的类MyClass的实例拥有类型MyClass。除了用户定义的命名型类型,Swift 标准库也定义了很多常用的命名型类型,包括那些表示数组、字典和可选值的类型。
|
||||||
|
|
||||||
那些通常被其它语言认为是基本或初级的数据型类型(Data types)——比如表示数字、字符和字符串——实际上就是命名型类型,Swift 标准库是使用结构体定义和实现它们的。因为它们是命名型类型,因此你可以按照“扩展和扩展声明”章节里讨论的那样,声明一个扩展来增加它们的行为以适应你程序的需求。
|
那些通常被其它语言认为是基本或初级的数据型类型(Data types)——比如表示数字、字符和字符串的类型——实际上就是命名型类型,这些类型在Swift 标准库中是使用结构体来定义和实现的。因为它们是命名型类型,因此你可以按照“扩展和扩展声明”章节里讨论的那样,声明一个扩展来增加它们的行为以迎合你程序的需求。
|
||||||
|
|
||||||
*复合型类型*是没有名字的类型,它由 Swift 本身定义。Swift 存在两种复合型类型:函数类型和元组类型。一个复合型类型可以包含命名型类型和其它复合型类型。例如,元组类型`(Int, (Int, Int))`包含两个元素:第一个是命名型类型`Int`,第二个是另一个复合型类型`(Int, Int)`.
|
*复合型类型*是没有名字的类型,它由 Swift 本身定义。Swift 存在两种复合型类型:函数类型和元组类型。一个复合型类型可以包含命名型类型和其它复合型类型。例如,元组类型(Int, (Int, Int))包含两个元素:第一个是命名型类型Int,第二个是另一个复合型类型(Int, Int).
|
||||||
|
|
||||||
本节讨论 Swift 语言本身定义的类型,并描述 Swift 中的类型推断行为。
|
本节讨论 Swift 语言本身定义的类型,并描述 Swift 中的类型推断行为。
|
||||||
|
|
||||||
> 类型语法
|
> 类型语法
|
||||||
> *类型* → [*数组类型*](..\chapter3\03_Types.html#array_type) | [*函数类型*](..\chapter3\03_Types.html#function_type) | [*类型标识*](..\chapter3\03_Types.html#type_identifier) | [*元组类型*](..\chapter3\03_Types.html#tuple_type) | [*可选类型*](..\chapter3\03_Types.html#optional_type) | [*隐式解析可选类型*](..\chapter3\03_Types.html#implicitly_unwrapped_optional_type) | [*协议合成类型*](..\chapter3\03_Types.html#protocol_composition_type) | [*元型类型*](..\chapter3\03_Types.html#metatype_type)
|
> *类型* → [*数组类型*](#array_type) | [*字典类型*](..\chapter3\03_Types.html#dictionary_type) | [*函数类型*](..\chapter3\03_Types.html#function_type) | [*类型标识*](..\chapter3\03_Types.html#type_identifier) | [*元组类型*](..\chapter3\03_Types.html#tuple_type) | [*可选类型*](..\chapter3\03_Types.html#optional_type) | [*隐式解析可选类型*](..\chapter3\03_Types.html#implicitly_unwrapped_optional_type) | [*协议合成类型*](..\chapter3\03_Types.html#protocol_composition_type) | [*元型类型*](..\chapter3\03_Types.html#metatype_type)
|
||||||
|
|
||||||
<a name="type_annotation"></a>
|
<a name="type_annotation"></a>
|
||||||
##类型注解
|
##类型注解
|
||||||
@ -50,9 +50,9 @@ func someFunction(a: Int){ /* ... */ }
|
|||||||
|
|
||||||
类型标识符引用命名型类型或者是命名型/复合型类型的别名。
|
类型标识符引用命名型类型或者是命名型/复合型类型的别名。
|
||||||
|
|
||||||
大多数情况下,类型标识符引用的是同名的命名型类型。例如类型标识符`Int`引用命名型类型`Int`,同样,类型标识符`Dictionary<String, Int>`引用命名型类型`Dictionary<String, Int>`。
|
大多数情况下,类型标识符引用的是与之同名的命名型类型。例如类型标识符`Int`引用命名型类型`Int`,同样,类型标识符`Dictionary<String, Int>`引用命名型类型`Dictionary<String, Int>`。
|
||||||
|
|
||||||
在两种情况下类型标识符引用的不是同名的类型。情况一,类型标识符引用的是命名型/复合型类型的类型别名。比如,在下面的例子中,类型标识符使用`Point`来引用元组`(Int, Int)`:
|
在两种情况下类型标识符不引用同名的类型。情况一,类型标识符引用的是命名型/复合型类型的类型别名。比如,在下面的例子中,类型标识符使用`Point`来引用元组`(Int, Int)`:
|
||||||
|
|
||||||
```swift
|
```swift
|
||||||
typealias Point = (Int, Int)
|
typealias Point = (Int, Int)
|
||||||
@ -74,9 +74,9 @@ var someValue: ExampleModule.MyType
|
|||||||
|
|
||||||
元组类型使用逗号隔开并使用括号括起来的0个或多个类型组成的列表。
|
元组类型使用逗号隔开并使用括号括起来的0个或多个类型组成的列表。
|
||||||
|
|
||||||
你可以使用元组类型作为一个函数的返回类型,这样就可以使函数返回多个值。你也可以命名元组类型中的元素,然后用这些名字来引用每个元素的值。元素的名字由一个标识符和`:`组成。“函数和多返回值”章节里有一个展示上述特性的例子。
|
你可以使用元组类型作为一个函数的返回类型,这样就可以使函数返回多个值。你也可以命名元组类型中的元素,然后用这些名字来引用每个元素的值。元素的名字由一个标识符紧跟一个冒号`(:)`组成。“函数和多返回值”章节里有一个展示上述特性的例子。
|
||||||
|
|
||||||
`void`是空元组类型`()`的别名。如果括号内只有一个元素,那么该类型就是括号内元素的类型。比如,`(Int)`的类型是`Int`而不是`(Int)`。所以,只有当元组类型包含两个元素以上时才可以标记元组元素。
|
`void`是空元组类型`()`的别名。如果括号内只有一个元素,那么该类型就是括号内元素的类型。比如,`(Int)`的类型是`Int`而不是`(Int)`。所以,只有当元组类型包含的元素个数在两个及以上时才可以命名元组元素。
|
||||||
|
|
||||||
> 元组类型语法
|
> 元组类型语法
|
||||||
> *元组类型* → **(** [*元组类型主体*](..\chapter3\03_Types.html#tuple_type_body) _可选_ **)**
|
> *元组类型* → **(** [*元组类型主体*](..\chapter3\03_Types.html#tuple_type_body) _可选_ **)**
|
||||||
@ -90,54 +90,39 @@ var someValue: ExampleModule.MyType
|
|||||||
|
|
||||||
函数类型表示一个函数、方法或闭包的类型,它由一个参数类型和返回值类型组成,中间用箭头`->`隔开:
|
函数类型表示一个函数、方法或闭包的类型,它由一个参数类型和返回值类型组成,中间用箭头`->`隔开:
|
||||||
|
|
||||||
- `parameter type` -> `return type`
|
`parameter type` -> `return type`
|
||||||
|
|
||||||
由于 *参数类型* 和 *返回值类型* 可以是元组类型,所以函数类型可以让函数与方法支持多参数与多返回值。
|
由于 *参数类型* 和 *返回值类型* 可以是元组类型,所以函数类型支持多参数与多返回值的函数与方法。。
|
||||||
|
|
||||||
你可以对函数类型应用带有参数类型`()`并返回表达式类型的`auto_closure`属性(见类型属性章节)。一个自动闭包函数捕获特定表达式上的隐式闭包而非表达式本身。下面的例子使用`auto_closure`属性来定义一个很简单的assert函数:
|
对于参数类型是空元组类型`()`以及返回值类型为表达式类型的函数类型,你可以对其参数声明使用`autoclosure`(见声明属性章节)。一个自动闭包函数捕获特定表达式上的隐式闭包而非表达式本身。下面的例子使用`autoclosure`属性来定义一个很简单的assert函数:
|
||||||
|
|
||||||
```swift
|
```swift
|
||||||
func simpleAssert(condition: @auto_closure () -> Bool, message: String){
|
func simpleAssert(@autoclosure condition: Void -> Bool, _ message: String) {
|
||||||
if !condition() {
|
if !condition() {
|
||||||
println(message)
|
print(message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let testNumber = 5
|
let testNumber = 5
|
||||||
simpleAssert(testNumber % 2 == 0, "testNumber isn't an even number.")
|
simpleAssert(testNumber % 2 == 0, "testNumber isn't an even number.")
|
||||||
// prints "testNumber isn't an even number."
|
// prints "testNumber isn't an even number."
|
||||||
```
|
```
|
||||||
函数类型可以拥有一个可变长参数作为参数类型中的最后一个参数。从语法角度上讲,可变长参数由一个基础类型名字和`...`组成,如`Int...`。可变长参数被认为是一个包含了基础类型元素的数组。即`Int...`就是`Int[]`。关于使用可变长参数的例子,见章节“可变长参数”。
|
函数类型可以拥有一个可变长参数作为参数类型中的最后一个参数。从语法角度上讲,可变长参数由一个基础类型名字紧随三个点`(...)`组成,如`Int...`。可变长参数被认为是一个包含了基础类型元素的数组。即`Int...`就是`[Int]`。关于使用可变长参数的例子,见章节Variadic Parameters。
|
||||||
|
|
||||||
为了指定一个`in-out`参数,可以在参数类型前加`inout`前缀。但是你不可以对可变长参数或返回值类型使用`inout`。关于In-Out参数的讨论见章节In-Out参数部分。
|
为了指定一个`in-out`参数,可以在参数类型前加`inout`前缀。但是你不可以对可变长参数或返回值类型使用`inout`。关于In-Out参数的讨论见章节In-Out参数部分。
|
||||||
|
|
||||||
柯里化函数(curried function)的类型相当于一个嵌套函数类型。例如,下面的柯里化函数`addTwoNumber()()`的类型是`Int -> Int -> Int`:
|
柯里化函数(Curried fuction)的函数类型从右向左递归地组成一组。例如,函数类型`Int -> Int -> Int`可以被理解为`Int -> (Int -> Int)`——也就是说,一个函数的参数为`Int`类型,其返回类型是一个参数类型为`Int`返回类型为`Int`的函数类型。关于柯里化函数的讨论见章节Curried Fuctions。
|
||||||
|
|
||||||
```swift
|
函数类型若要抛出错误就必须使用`throws`关键字来标记,若要重抛错误则必须使用`rethrows`关键字来标记。`throws`关键字是函数类型的一部分,不抛出函数(nonthrowing function)是抛出函数(throwing function)函数的一个子类型。因此,在使用抛出函数的地方也可以使用不抛出函数。对于柯里化函数,`throws`关键字只应用于最里层的函数。抛出和重抛函数(rethrowing function)的相关描述见章节抛出函数与方法和重抛函数与方法。
|
||||||
func addTwoNumbers(a: Int)(b: Int) -> Int{
|
|
||||||
return a + b
|
|
||||||
}
|
|
||||||
addTwoNumbers(4)(5) // returns 9
|
|
||||||
```
|
|
||||||
|
|
||||||
柯里化函数的函数类型从右向左组成一组。例如,函数类型`Int -> Int -> Int`可以被理解为`Int -> (Int -> Int)`——也就是说,一个函数传入一个`Int`然后输出作为另一个函数的输入,然后又返回一个`Int`。例如,你可以使用如下嵌套函数来重写柯里化函数`addTwoNumbers()()`:
|
|
||||||
|
|
||||||
```swift
|
|
||||||
func addTwoNumbers(a: Int) -> (Int -> Int){
|
|
||||||
func addTheSecondNumber(b: Int) -> Int{
|
|
||||||
return a + b
|
|
||||||
}
|
|
||||||
return addTheSecondNumber
|
|
||||||
}
|
|
||||||
addTwoNumbers(4)(5) // Returns 9
|
|
||||||
```
|
|
||||||
|
|
||||||
> 函数类型语法
|
> 函数类型语法
|
||||||
> *函数类型* → [*类型*](..\chapter3\03_Types.html#type) **->** [*类型*](..\chapter3\03_Types.html#type)
|
> *函数类型* → [*类型*](..\chapter3\03_Types.html#type) _抛出_ _可选_ **->** [*类型*](..\chapter3\03_Types.html#type)
|
||||||
|
> *函数类型* → [*类型*](..\chapter3\03_Types.html#type)_重抛_ **->** [*类型*](..\chapter3\03_Types.html#type)
|
||||||
|
|
||||||
<a name="array_type"></a>
|
<a name="array_type"></a>
|
||||||
##数组类型
|
##数组类型
|
||||||
|
|
||||||
Swift语言使用类型名紧接中括号`[]`来简化标准库中定义的命名型类型`Array<T>`。换句话说,下面两个声明是等价的:
|
Swift语言中使用[`type`]来简化标准库中定义`Array<T>`类型的操作。
|
||||||
|
换句话说,下面两个声明是等价的:
|
||||||
|
|
||||||
```swift
|
```swift
|
||||||
let someArray: String[] = ["Alex", "Brian", "Dave"]
|
let someArray: String[] = ["Alex", "Brian", "Dave"]
|
||||||
@ -145,22 +130,38 @@ let someArray: Array<String> = ["Alex", "Brian", "Dave"]
|
|||||||
```
|
```
|
||||||
上面两种情况下,常量`someArray`都被声明为字符串数组。数组的元素也可以通过`[]`获取访问:`someArray[0]`是指第0个元素`“Alex”`。
|
上面两种情况下,常量`someArray`都被声明为字符串数组。数组的元素也可以通过`[]`获取访问:`someArray[0]`是指第0个元素`“Alex”`。
|
||||||
|
|
||||||
上面的例子同时显示,你可以使用`[]`作为初始值构造数组,空的`[]`则用来来构造指定类型的空数组。
|
你也可以嵌套多对方括号来创建多维数组,最里面的方括号中指明数组元素的基本类型。比如,下面例子中使用三对方括号创建三维整数数组。
|
||||||
|
|
||||||
```swift
|
```swift
|
||||||
var emptyArray: Double[] = []
|
var array3D: [[[Int]]] = [[[1, 2], [3, 4]], [[5, 6], [7, 8]]]
|
||||||
```
|
|
||||||
你也可以使用链接起来的多个`[]`集合来构造多维数组。例如,下例使用三个`[]`集合来构造三维整型数组:
|
|
||||||
|
|
||||||
```swift
|
|
||||||
var array3D: Int[][][] = [[[1, 2], [3, 4]], [[5, 6], [7, 8]]]
|
|
||||||
```
|
```
|
||||||
访问一个多维数组的元素时,最左边的下标指向最外层数组的相应位置元素。接下来往右的下标指向第一层嵌入的相应位置元素,依次类推。这就意味着,在上面的例子中,`array3D[0]`是指`[[1, 2], [3, 4]]`,`array3D[0][1]`是指`[3, 4]`,`array3D[0][1][1]`则是指值`4`。
|
访问一个多维数组的元素时,最左边的下标指向最外层数组的相应位置元素。接下来往右的下标指向第一层嵌入的相应位置元素,依次类推。这就意味着,在上面的例子中,`array3D[0]`是指`[[1, 2], [3, 4]]`,`array3D[0][1]`是指`[3, 4]`,`array3D[0][1][1]`则是指值`4`。
|
||||||
|
|
||||||
关于Swift标准库中`Array`类型的细节讨论,见章节Arrays。
|
关于Swift标准库中`Array`类型的细节讨论,见章节Arrays。
|
||||||
|
|
||||||
> 数组类型语法
|
> 数组类型语法
|
||||||
> *数组类型* → [*类型*](..\chapter3\03_Types.html#type) **[** **]** | [*数组类型*](..\chapter3\03_Types.html#array_type) **[** **]**
|
> *数组类型* → [*类型*](..\chapter3\03_Types.html#type)
|
||||||
|
|
||||||
|
<a name="dictionary_type"></a>
|
||||||
|
##字典类型
|
||||||
|
|
||||||
|
Swift语言中使用[`key type: value type`]来简化标准库中定义`Dictionary<Key,Value>`类型的操作。
|
||||||
|
换句话说,下面两个声明是等价的:
|
||||||
|
|
||||||
|
```swift
|
||||||
|
let someDictionary: [String: Int] = ["Alex": 31, "Paul": 39]
|
||||||
|
let someDictionary: Dictionary<String, Int> = ["Alex": 31, "Paul": 39]
|
||||||
|
```
|
||||||
|
上面两种情况,常量`someDictionary`被声明为一个字典,其中键为String类型,值为Int类型。
|
||||||
|
|
||||||
|
字典中的值可以通过下标来访问,这个下标在方括号中指明了具体的键:`someDictionary["Alex"]`返回键`Alex`对应的值。如果键在字典中不存在的话,则这个下标返回`nil`。
|
||||||
|
|
||||||
|
字典中键的类型必须遵循Swift标准库中的可哈希协议。
|
||||||
|
|
||||||
|
关于Swift标准库中`Dictionary`类型的更多细节可查看章节Dictionaries。
|
||||||
|
|
||||||
|
> 字典类型语法
|
||||||
|
> *字典类型* → **[**[*类型*](..\chapter3\03_Types.html#type) **:** [*类型*](..\chapter3\03_Types.html#type) **]**
|
||||||
|
|
||||||
<a name="optional_type"></a>
|
<a name="optional_type"></a>
|
||||||
##可选类型
|
##可选类型
|
||||||
@ -177,8 +178,6 @@ var optionalInteger: Optional<Int>
|
|||||||
|
|
||||||
如果你在声明或定义可选变量或特性的时候没有提供初始值,它的值则会自动赋成缺省值`nil`。
|
如果你在声明或定义可选变量或特性的时候没有提供初始值,它的值则会自动赋成缺省值`nil`。
|
||||||
|
|
||||||
可选符合`LogicValue`协议,因此可以出现在布尔值环境下。此时,如果一个可选类型`T?`实例包含有类型为`T`的值(也就是说值为`Optional.Some(T)`),那么此可选类型就为`true`,否则为`false`。
|
|
||||||
|
|
||||||
如果一个可选类型的实例包含一个值,那么你就可以使用后缀操作符`!`来获取该值,正如下面描述的:
|
如果一个可选类型的实例包含一个值,那么你就可以使用后缀操作符`!`来获取该值,正如下面描述的:
|
||||||
|
|
||||||
```swift
|
```swift
|
||||||
@ -189,7 +188,7 @@ optionalInteger! // 42
|
|||||||
|
|
||||||
你也可以使用可选链和可选绑定来选择性的执行可选表达式上的操作。如果值为`nil`,不会执行任何操作因此也就没有运行错误产生。
|
你也可以使用可选链和可选绑定来选择性的执行可选表达式上的操作。如果值为`nil`,不会执行任何操作因此也就没有运行错误产生。
|
||||||
|
|
||||||
更多细节以及更多如何使用可选类型的例子,见章节“可选”。
|
更多细节以及更多如何使用可选类型的例子,见章节Optionals。
|
||||||
|
|
||||||
> 可选类型语法
|
> 可选类型语法
|
||||||
> *可选类型* → [*类型*](..\chapter3\03_Types.html#type) **?**
|
> *可选类型* → [*类型*](..\chapter3\03_Types.html#type) **?**
|
||||||
@ -205,7 +204,7 @@ var implicitlyUnwrappedString: ImplicitlyUnwrappedOptional<String>
|
|||||||
```
|
```
|
||||||
上述两种情况下,变量`implicitlyUnwrappedString`被声明为一个隐式解析可选类型的字符串。注意类型与`!`之间没有空格。
|
上述两种情况下,变量`implicitlyUnwrappedString`被声明为一个隐式解析可选类型的字符串。注意类型与`!`之间没有空格。
|
||||||
|
|
||||||
你可以在使用可选的地方同样使用隐式解析可选。比如,你可以将隐式解析可选的值赋给变量、常量和可选特性,反之亦然。
|
你可以在使用可选类型的地方同样使用隐式解析可选类型。比如,你可以将隐式解析可选类型的值赋给变量、常量和可选特性,反之亦然。
|
||||||
|
|
||||||
有了可选,你在声明隐式解析可选变量或特性的时候就不用指定初始值,因为它有缺省值`nil`。
|
有了可选,你在声明隐式解析可选变量或特性的时候就不用指定初始值,因为它有缺省值`nil`。
|
||||||
|
|
||||||
@ -213,7 +212,7 @@ var implicitlyUnwrappedString: ImplicitlyUnwrappedOptional<String>
|
|||||||
|
|
||||||
使用可选链会选择性的执行隐式解析可选表达式上的某一个操作。如果值为`nil`,就不会执行任何操作,因此也不会产生运行错误。
|
使用可选链会选择性的执行隐式解析可选表达式上的某一个操作。如果值为`nil`,就不会执行任何操作,因此也不会产生运行错误。
|
||||||
|
|
||||||
关于隐式解析可选的更多细节,见章节“隐式解析可选”。
|
关于隐式解析可选的更多细节,见章节Implicitly Unwrapped Optionals。
|
||||||
|
|
||||||
> 隐式解析可选类型(Implicitly Unwrapped Optional Type)语法
|
> 隐式解析可选类型(Implicitly Unwrapped Optional Type)语法
|
||||||
> *隐式解析可选类型* → [*类型*](..\chapter3\03_Types.html#type) **!**
|
> *隐式解析可选类型* → [*类型*](..\chapter3\03_Types.html#type) **!**
|
||||||
@ -221,7 +220,7 @@ var implicitlyUnwrappedString: ImplicitlyUnwrappedOptional<String>
|
|||||||
<a name="protocol_composition_type"></a>
|
<a name="protocol_composition_type"></a>
|
||||||
##协议合成类型
|
##协议合成类型
|
||||||
|
|
||||||
协议合成类型是一种符合每个协议的指定协议列表类型。协议合成类型可能会用在类型注解和泛型参数中。
|
协议合成类型是一种遵循具体协议列表中每个协议的类型。协议合成类型可能会用在类型注解和泛型参数中。
|
||||||
|
|
||||||
协议合成类型的形式如下:
|
协议合成类型的形式如下:
|
||||||
|
|
||||||
@ -229,9 +228,9 @@ var implicitlyUnwrappedString: ImplicitlyUnwrappedOptional<String>
|
|||||||
protocol<Protocol 1, Procotol 2>
|
protocol<Protocol 1, Procotol 2>
|
||||||
```
|
```
|
||||||
|
|
||||||
协议合成类型允许你指定一个值,其类型可以适配多个协议的条件,而且不需要定义一个新的命名型协议来继承其它想要适配的各个协议。比如,协议合成类型`protocol<Protocol A, Protocol B, Protocol C>`等效于一个从`Protocol A`,`Protocol B`, `Protocol C`继承而来的新协议`Protocol D`,很显然这样做有效率的多,甚至不需引入一个新名字。
|
协议合成类型允许你指定一个值,其类型遵循多个协议的条件且不需要定义一个新的命名型协议来继承其它想要遵循的各个协议。比如,协议合成类型`protocol<Protocol A, Protocol B, Protocol C>`等效于一个从`Protocol A`,`Protocol B`, `Protocol C`继承而来的新协议`Protocol D`,很显然这样做有效率的多,甚至不需引入一个新名字。
|
||||||
|
|
||||||
协议合成列表中的每项必须是协议名或协议合成类型的类型别名。如果列表为空,它就会指定一个空协议合成列表,这样每个类型都能适配。
|
协议合成列表中的每项必须是协议名或协议合成类型的类型别名。如果列表为空,它就会指定一个空协议合成列表,这样每个类型都能遵循。
|
||||||
|
|
||||||
> 协议合成类型语法
|
> 协议合成类型语法
|
||||||
> *协议合成类型* → **protocol** **<** [*协议标识符列表*](..\chapter3\03_Types.html#protocol_identifier_list) _可选_ **>**
|
> *协议合成类型* → **protocol** **<** [*协议标识符列表*](..\chapter3\03_Types.html#protocol_identifier_list) _可选_ **>**
|
||||||
@ -243,9 +242,9 @@ protocol<Protocol 1, Procotol 2>
|
|||||||
|
|
||||||
元类型是指所有类型的类型,包括类、结构体、枚举和协议。
|
元类型是指所有类型的类型,包括类、结构体、枚举和协议。
|
||||||
|
|
||||||
类、结构体或枚举类型的元类型是相应的类型名紧跟`.Type`。协议类型的元类型——并不是运行时适配该协议的具体类型——是该协议名字紧跟`.Protocol`。比如,类`SomeClass`的元类型就是`SomeClass.Type`,协议`SomeProtocol`的元类型就是`SomeProtocal.Protocol`。
|
类、结构体或枚举类型的元类型是相应的类型名紧跟`.Type`。协议类型的元类型——并不是运行时遵循该协议的具体类型——是该协议名字紧跟`.Protocol`。比如,类`SomeClass`的元类型就是`SomeClass.Type`,协议`SomeProtocol`的元类型就是`SomeProtocal.Protocol`。
|
||||||
|
|
||||||
你可以使用后缀`self`表达式来获取类型。比如,`SomeClass.self`返回`SomeClass`本身,而不是`SomeClass`的一个实例。同样,`SomeProtocol.self`返回`SomeProtocol`本身,而不是运行时适配`SomeProtocol`的某个类型的实例。还可以对类型的实例使用`dynamicType`表达式来获取该实例在运行阶段的类型,如下所示:
|
你可以使用后缀`self`表达式来获取类型。比如,`SomeClass.self`返回`SomeClass`本身,而不是`SomeClass`的一个实例。同样,`SomeProtocol.self`返回`SomeProtocol`本身,而不是运行时遵循`SomeProtocol`的某个类型的实例。还可以对类型的实例使用`dynamicType`表达式来获取该实例在运行阶段的类型,如下所示:
|
||||||
|
|
||||||
```swift
|
```swift
|
||||||
class SomeBaseClass {
|
class SomeBaseClass {
|
||||||
@ -264,29 +263,35 @@ let someInstance: SomeBaseClass = SomeSubClass()
|
|||||||
someInstance.dynamicType.printClassName()
|
someInstance.dynamicType.printClassName()
|
||||||
// prints "SomeSubClass
|
// prints "SomeSubClass
|
||||||
```
|
```
|
||||||
|
> 注意
|
||||||
|
> **不能创建元类型类的实例,因为不能保证其子类会提供初始化的代码。**
|
||||||
|
|
||||||
|
|
||||||
> 元(Metatype)类型语法
|
> 元(Metatype)类型语法
|
||||||
> *元类型* → [*类型*](..\chapter3\03_Types.html#type) **.** **Type** | [*类型*](..\chapter3\03_Types.html#type) **.** **Protocol** x
|
> *元类型* → [*类型*](..\chapter3\03_Types.html#type) **.** **Type** | [*类型*](..\chapter3\03_Types.html#type) **.** **Protocol**
|
||||||
|
|
||||||
<a name="type_inheritance_clause"></a>
|
<a name="type_inheritance_clause"></a>
|
||||||
##类型继承子句
|
##类型继承子句
|
||||||
|
|
||||||
类型继承子句被用来指定一个命名型类型继承哪个类且适配哪些协议。类型继承子句开始于冒号`:`,紧跟由`,`隔开的类型标识符列表。
|
类型继承子句被用来指定一个命名型类型继承的哪个类、遵循的哪些协议。类型继承子句也用来指定一个类需要遵循的协议。类型继承子句开始于冒号`:`,其后是类所需遵循的协议或者类型标识符列表或者两者均有。
|
||||||
|
|
||||||
类可以继承单个超类,适配任意数量的协议。当定义一个类时,超类的名字必须出现在类型标识符列表首位,然后跟上该类需要适配的任意数量的协议。如果一个类不是从其它类继承而来,那么列表可以以协议开头。关于类继承更多的讨论和例子,见章节“继承”。
|
类可以继承单个超类,遵循任意数量的协议。当定义一个类时,超类的名字必须出现在类型标识符列表首位,然后跟上该类需要遵循的任意数量的协议。如果一个类不是从其它类继承而来,那么列表可以以协议开头。关于类继承更多的讨论和例子,见章节Inheritance。
|
||||||
|
|
||||||
其它命名型类型可能只继承或适配一个协议列表。协议类型可能继承于其它任意数量的协议。当一个协议类型继承于其它协议时,其它协议的条件集合会被集成在一起,然后其它从当前协议继承的任意类型必须适配所有这些条件。
|
其它命名型类型可能只继承或遵循一个协议列表。协议类型可能继承于其它任意数量的协议。当一个协议类型继承于其它协议时,其它协议的条件集合会被整合在一起,然后其它从当前协议继承的任意类型必须遵循所有这些条件。正如在协议声明中所讨论的那样,可以把类的关键字放到类型继承子句中的首位,这样就可以用一个类的条件来标记一个协议声明。
|
||||||
|
|
||||||
枚举定义中的类型继承子句可以是一个协议列表,或是指定原始值的枚举,一个单独的指定原始值类型的命名型类型。使用类型继承子句来指定原始值类型的枚举定义的例子,见章节“原始值”。
|
枚举定义中的类型继承子句可以是一个协议列表,或是指定原始值的枚举——一个单独的指定原始值类型的命名型类型。使用类型继承子句来指定原始值类型的枚举定义的例子,见章节Raw Values。
|
||||||
|
|
||||||
> 类型继承子句语法
|
> 类型继承子句语法
|
||||||
|
> *类型继承子句* → **:** [*类需求*](..\chapter3\03_Types.html#class_requirement) **,** [*类型继承列表*](..\chapter3\03_Types.html#type_inheritance_list)
|
||||||
|
> *类型继承子句* → **:** [*类需求*](..\chapter3\03_Types.html#class_requirement)
|
||||||
> *类型继承子句* → **:** [*类型继承列表*](..\chapter3\03_Types.html#type_inheritance_list)
|
> *类型继承子句* → **:** [*类型继承列表*](..\chapter3\03_Types.html#type_inheritance_list)
|
||||||
> *类型继承列表* → [*类型标识*](..\chapter3\03_Types.html#type_identifier) | [*类型标识*](..\chapter3\03_Types.html#type_identifier) **,** [*类型继承列表*](..\chapter3\03_Types.html#type_inheritance_list)
|
> *类型继承列表* → [*类型标识*](..\chapter3\03_Types.html#type_identifier) | [*类型标识*](..\chapter3\03_Types.html#type_identifier) **,** [*类型继承列表*](..\chapter3\03_Types.html#type_inheritance_list)
|
||||||
|
> *类需求* → **类**
|
||||||
|
|
||||||
<a name="type_inference"></a>
|
<a name="type_inference"></a>
|
||||||
##类型推断
|
##类型推断
|
||||||
|
|
||||||
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>`。
|
||||||
|
|
||||||
在上面的两个例子中,类型信息从表达式树(expression tree)的叶子节点传向根节点。也就是说,`var x: Int = 0`中`x`的类型首先根据`0`的类型进行推断,然后将该类型信息传递到根节点(变量`x`)。
|
在上面的两个例子中,类型信息从表达式树(expression tree)的叶子节点传向根节点。也就是说,`var x: Int = 0`中`x`的类型首先根据`0`的类型进行推断,然后将该类型信息传递到根节点(变量`x`)。
|
||||||
|
|
||||||
|
|||||||
196
source/chapter3/04_Expressions.md
Executable file → Normal file
196
source/chapter3/04_Expressions.md
Executable file → Normal file
@ -16,25 +16,16 @@
|
|||||||
|
|
||||||
Swift 中存在四种表达式: 前缀(prefix)表达式,二元(binary)表达式,主要(primary)表达式和后缀(postfix)表达式。表达式可以返回一个值,以及运行某些逻辑(causes a side effect)。
|
Swift 中存在四种表达式: 前缀(prefix)表达式,二元(binary)表达式,主要(primary)表达式和后缀(postfix)表达式。表达式可以返回一个值,以及运行某些逻辑(causes a side effect)。
|
||||||
|
|
||||||
前缀表达式和二元表达式就是对某些表达式使用各种运算符(operators)。 主要表达式是最短小的表达式,它提供了获取(变量的)值的一种途径。 后缀表达式则允许你建立复杂的表达式,例如配合函数调用和成员访问。 每种表达式都在下面有详细论述~
|
前缀表达式和二元表达式就是对某些表达式使用各种运算符(operators)。 主要表达式是最短小的表达式,它提供了获取(变量的)值的一种途径。 后缀表达式则允许你建立复杂的表达式,例如配合函数调用和成员访问。 每种表达式都在下面有详细论述。
|
||||||
|
|
||||||
> 表达式语法
|
> 表达式语法
|
||||||
> *表达式* → [*前置表达式*](..\chapter3\04_Expressions.html#prefix_expression) [*二元表达式列表*](..\chapter3\04_Expressions.html#binary_expressions) _可选_
|
> *表达式* → [*试算子(try operator)*](..\chapter3\04_Expressions.html#*) _可选_ | [*前置表达式*](..\chapter3\04_Expressions.html#prefix_expression) | [*二元表达式列表*](..\chapter3\04_Expressions.html#binary_expressions) _可选_
|
||||||
> *表达式列表* → [*表达式*](..\chapter3\04_Expressions.html#expression) | [*表达式*](..\chapter3\04_Expressions.html#expression) **,** [*表达式列表*](..\chapter3\04_Expressions.html#expression_list)
|
> *表达式列表* → [*表达式*](..\chapter3\04_Expressions.html#expression) | [*表达式*](..\chapter3\04_Expressions.html#expression) **,** [*表达式列表*](..\chapter3\04_Expressions.html#expression_list)
|
||||||
|
|
||||||
<a name="prefix_expressions"></a>
|
<a name="prefix_expressions"></a>
|
||||||
## 前缀表达式(Prefix Expressions)
|
## 前缀表达式(Prefix Expressions)
|
||||||
|
|
||||||
前缀表达式由 前缀符号和表达式组成。(这个前缀符号只能接收一个参数)
|
前缀表达式由可选的前缀符号和表达式组成。(这个前缀符号只能接收一个参数)
|
||||||
|
|
||||||
Swift 标准库支持如下的前缀操作符:
|
|
||||||
|
|
||||||
- ++ 自增1 (increment)
|
|
||||||
- -- 自减1 (decrement)
|
|
||||||
- ! 逻辑否 (Logical NOT )
|
|
||||||
- ~ 按位否 (Bitwise NOT )
|
|
||||||
- \+ 加(Unary plus)
|
|
||||||
- \- 减(Unary minus)
|
|
||||||
|
|
||||||
对于这些操作符的使用,请参见: Basic Operators and Advanced Operators
|
对于这些操作符的使用,请参见: Basic Operators and Advanced Operators
|
||||||
|
|
||||||
@ -45,6 +36,16 @@ Swift 标准库支持如下的前缀操作符:
|
|||||||
> *前置表达式* → [*写入写出(in-out)表达式*](..\chapter3\04_Expressions.html#in_out_expression)
|
> *前置表达式* → [*写入写出(in-out)表达式*](..\chapter3\04_Expressions.html#in_out_expression)
|
||||||
> *写入写出(in-out)表达式* → **&** [*标识符*](LexicalStructure.html#identifier)
|
> *写入写出(in-out)表达式* → **&** [*标识符*](LexicalStructure.html#identifier)
|
||||||
|
|
||||||
|
<a name="try_operator"></a>
|
||||||
|
## try 操作符(try operator)
|
||||||
|
try表达式由紧跟在可能会出错的表达式后面的`try`操作符组成,形式如下:
|
||||||
|
`try expression`
|
||||||
|
强制的try表示由紧跟在可能会出错的表达式后面的`try!`操作符组成,出错时会产生一个运行时错误,形式如下:
|
||||||
|
`try! expression`
|
||||||
|
关于`try`更多的例子和信息请参见:Catching and Handling Errors.
|
||||||
|
> try表达式语法
|
||||||
|
> *try 操作符* → [*try*](LexicalStructure.html#try_operator) | *try!*
|
||||||
|
|
||||||
<a name="binary_expressions"></a>
|
<a name="binary_expressions"></a>
|
||||||
## 二元表达式(Binary Expressions)
|
## 二元表达式(Binary Expressions)
|
||||||
|
|
||||||
@ -52,76 +53,18 @@ Swift 标准库支持如下的前缀操作符:
|
|||||||
|
|
||||||
> `left-hand argument` `operator` `right-hand argument`
|
> `left-hand argument` `operator` `right-hand argument`
|
||||||
|
|
||||||
Swift 标准库提供了如下的二元运算符:
|
|
||||||
|
|
||||||
- 求幂相关(无结合,优先级160)
|
|
||||||
- << 按位左移(Bitwise left shift)
|
|
||||||
- >> 按位右移(Bitwise right shift)
|
|
||||||
- 乘除法相关(左结合,优先级150)
|
|
||||||
- \* 乘
|
|
||||||
- / 除
|
|
||||||
- % 求余
|
|
||||||
- &* 乘法,忽略溢出( Multiply, ignoring overflow)
|
|
||||||
- &/ 除法,忽略溢出(Divide, ignoring overflow)
|
|
||||||
- &% 求余, 忽略溢出( Remainder, ignoring overflow)
|
|
||||||
- & 位与( Bitwise AND)
|
|
||||||
- 加减法相关(左结合, 优先级140)
|
|
||||||
- \+ 加
|
|
||||||
- \- 减
|
|
||||||
- &+ Add with overflow
|
|
||||||
- &- Subtract with overflow
|
|
||||||
- | 按位或(Bitwise OR )
|
|
||||||
- ^ 按位异或(Bitwise XOR)
|
|
||||||
- Range (无结合,优先级 135)
|
|
||||||
- ..< 半闭值域 Half-closed range
|
|
||||||
- ... 全闭值域 Closed range
|
|
||||||
- 类型转换 (无结合,优先级 132)
|
|
||||||
- is 类型检查( type check)
|
|
||||||
- as 类型转换( type cast)
|
|
||||||
- Comparative (无结合,优先级 130)
|
|
||||||
- < 小于
|
|
||||||
- <= 小于等于
|
|
||||||
- > 大于
|
|
||||||
- >= 大于等于
|
|
||||||
- == 等于
|
|
||||||
- != 不等
|
|
||||||
- === 恒等于
|
|
||||||
- !== 不恒等
|
|
||||||
- ~= 模式匹配( Pattern match)
|
|
||||||
- 合取( Conjunctive) (左结合,优先级 120)
|
|
||||||
- && 逻辑与(Logical AND)
|
|
||||||
- 析取(Disjunctive) (左结合,优先级 110)
|
|
||||||
- || 逻辑或( Logical OR)
|
|
||||||
- 三元条件(Ternary Conditional )(右结合,优先级 100)
|
|
||||||
- ?: 三元条件 Ternary conditional
|
|
||||||
- 赋值 (Assignment) (右结合, 优先级 90)
|
|
||||||
- = 赋值(Assign)
|
|
||||||
- *= Multiply and assign
|
|
||||||
- /= Divide and assign
|
|
||||||
- %= Remainder and assign
|
|
||||||
- += Add and assign
|
|
||||||
- -= Subtract and assign
|
|
||||||
- <<= Left bit shift and assign
|
|
||||||
- >>= Right bit shift and assign
|
|
||||||
- &= Bitwise AND and assign
|
|
||||||
- ^= Bitwise XOR and assign
|
|
||||||
- |= Bitwise OR and assign
|
|
||||||
- &&= Logical AND and assign
|
|
||||||
- ||= Logical OR and assign
|
|
||||||
|
|
||||||
关于这些运算符(operators)的更多信息,请参见:Basic Operators and Advanced Operators.
|
关于这些运算符(operators)的更多信息,请参见:Basic Operators and Advanced Operators.
|
||||||
|
|
||||||
> 注意
|
> 注意
|
||||||
> 在解析时, 一个二元表达式表示为一个一级数组(a flat list), 这个数组(List)根据运算符的先后顺序,被转换成了一个tree. 例如: 2 + 3 * 5 首先被认为是: 2, + , `` 3``, *, 5. 随后它被转换成 tree (2 + (3 * 5))
|
> 在解析时, 一个二元表达式表示为一个一级数组(a flat list), 这个数组(List)根据运算符的先后顺序,被转换成了一个tree. 例如: 2 + 3 * 5 首先被认为是: 2, + , `` 3``, *, 5. 随后它被转换成 tree (2 + (3 * 5))
|
||||||
|
|
||||||
<p></p>
|
|
||||||
|
|
||||||
> 二元表达式语法
|
> 二元表达式语法
|
||||||
> *二元表达式* → [*二元运算符*](LexicalStructure.html#binary_operator) [*前置表达式*](..\chapter3\04_Expressions.html#prefix_expression)
|
> *二元表达式* → [*二元运算符*](LexicalStructure.html#binary_operator) [*前置表达式*](..\chapter3\04_Expressions.html#prefix_expression)
|
||||||
> *二元表达式* → [*赋值运算符*](..\chapter3\04_Expressions.html#assignment_operator) [*前置表达式*](..\chapter3\04_Expressions.html#prefix_expression)
|
> *二元表达式* → [*赋值运算符*](..\chapter3\04_Expressions.html#assignment_operator) [*前置表达式*](..\chapter3\04_Expressions.html#prefix_expression)
|
||||||
> *二元表达式* → [*条件运算符*](..\chapter3\04_Expressions.html#conditional_operator) [*前置表达式*](..\chapter3\04_Expressions.html#prefix_expression)
|
> *二元表达式* → [*条件运算符*](..\chapter3\04_Expressions.html#conditional_operator) [*前置表达式*](..\chapter3\04_Expressions.html#prefix_expression)
|
||||||
> *二元表达式* → [*类型转换运算符*](..\chapter3\04_Expressions.html#type_casting_operator)
|
> *二元表达式* → [*类型转换运算符*](..\chapter3\04_Expressions.html#type_casting_operator)
|
||||||
> *二元表达式列表* → [*二元表达式*](..\chapter3\04_Expressions.html#binary_expression) [*二元表达式列表*](..\chapter3\04_Expressions.html#binary_expressions) _可选_
|
> *二元表达式列表* → [*二元表达式*](..\chapter3\04_Expressions.html#binary_expression) [*二元表达式列表*](..\chapter3\04_Expressions.html#binary_expressions) _可选_
|
||||||
|
> *赋值操作符*
|
||||||
|
|
||||||
|
|
||||||
<a name="assignment_operator"></a>
|
<a name="assignment_operator"></a>
|
||||||
@ -160,49 +103,43 @@ Swift 标准库提供了如下的二元运算符:
|
|||||||
<a name="type-casting_operators"></a>
|
<a name="type-casting_operators"></a>
|
||||||
## 类型转换运算符(Type-Casting Operators)
|
## 类型转换运算符(Type-Casting Operators)
|
||||||
|
|
||||||
有两种类型转换操作符: as 和 is. 它们有如下的形式:
|
有4种类型转换运算符: `is`,`as`,`? `和`!`. 它们有如下的形式:
|
||||||
|
|
||||||
> `expression` as `type`
|
|
||||||
> `expression` as? `type`
|
|
||||||
> `expression` is `type`
|
> `expression` is `type`
|
||||||
|
> `expression` as `type`
|
||||||
|
> `expression` is? `type`
|
||||||
|
> `expression` as! `type`
|
||||||
|
|
||||||
as 运算符会把`目标表达式`转换成指定的`类型`(specified type),过程如下:
|
`is`运算符在程序运行时检查表达式能否向下转化为指定的类型,如果可以在返回`ture`,如果不行,则返回`false`。
|
||||||
|
|
||||||
- 如果类型转换成功, 那么目标表达式就会返回指定类型的实例(instance). 例如:把子类(subclass)变成父类(superclass)时.
|
|
||||||
- 如果转换失败,则会抛出编译错误( compile-time error)。
|
|
||||||
- 如果上述两个情况都不是(也就是说,编译器在编译时期无法确定转换能否成功,) 那么目标表达式就会变成指定的类型的optional. (is an optional of the specified type ) 然后在运行时,如果转换成功, 目标表达式就会作为 optional的一部分来返回, 否则,目标表达式返回nil. 对应的例子是: 把一个 superclass 转换成一个 subclass.
|
|
||||||
|
|
||||||
|
`as`运算符在程序编译时执行类型转化,且总是成功,比如进行向上转换(upcast)和桥接(bridging)。向上转换指把表达式转换成类型的超类的一个是实例而不使用中间的变量。以下表达式是等价的:
|
||||||
```swift
|
```swift
|
||||||
class SomeSuperType {}
|
func f(any: Any) { print("Function for Any") }
|
||||||
class SomeType: SomeSuperType {}
|
func f(int: Int) { print("Function for Int") }
|
||||||
class SomeChildType: SomeType {}
|
let x = 10
|
||||||
let s = SomeType()
|
f(x)
|
||||||
|
// prints "Function for Int"
|
||||||
|
|
||||||
let x = s as SomeSuperType // known to succeed; type is SomeSuperType
|
let y: Any = x
|
||||||
let y = s as Int // known to fail; compile-time error
|
f(y)
|
||||||
let z = s as SomeChildType // might fail at runtime; type is SomeChildType?
|
// prints "Function for Any"
|
||||||
|
|
||||||
|
f(x as Any)
|
||||||
|
// prints "Function for Any"
|
||||||
```
|
```
|
||||||
|
桥接运算可以让你把一个Swift标准库中的类型的表达式作为一个与之相关的基础类(比如NSString)来使用,而不需要新建一个实例。关于桥接的更多实例参见Using Swift with Cocoa and Objective-C中的Cocoa Data Types。
|
||||||
|
|
||||||
使用'as'做类型转换跟正常的类型声明,对于编译器来说是一样的。例如:
|
`as?`操作符为带条件的类型转换。`as?`操作符返回可选的转换类型。在运行时,如果转换成功,表达式的值会被覆盖掉再返回,如果转换不成功的话,则返回`nil`。如果条件转换中的条件的真值一开始就已经确定真伪了,则在编译时会报错。
|
||||||
|
|
||||||
```swift
|
`a!`操作符表示强制转换,其返回指定的类型,而不是可选的类型。如果转换失败,则会出现运行时错误。表达式`x as T` 效果等同于`(x as? T)!`。
|
||||||
let y1 = x as SomeType // Type information from 'as'
|
|
||||||
let y2: SomeType = x // Type information from an annotation
|
|
||||||
```
|
|
||||||
|
|
||||||
'is' 运算符在“运行时(runtime)”会做检查。 成功会返回true, 否则 false
|
|
||||||
|
|
||||||
上述检查在“编译时(compile time)”不能使用。 例如下面的使用是错误的:
|
|
||||||
|
|
||||||
```swift
|
|
||||||
"hello" is String
|
|
||||||
"hello" is Int
|
|
||||||
```
|
|
||||||
|
|
||||||
关于类型转换的更多内容和例子,请参见: Type Casting.
|
关于类型转换的更多内容和例子,请参见: Type Casting.
|
||||||
|
|
||||||
> 类型转换运算符(type-casting-operator)语法
|
> 类型转换运算符(type-casting-operator)语法
|
||||||
> *类型转换运算符* → **is** [*类型*](..\chapter3\03_Types.html#type) | **as** **?** _可选_ [*类型*](..\chapter3\03_Types.html#type)
|
> *类型转换运算符* → **is** [*类型*](..\chapter3\03_Types.html#type)
|
||||||
|
> *类型转换运算符* → **as** [*类型*](..\chapter3\03_Types.html#type)
|
||||||
|
> *类型转换运算符* → **is** **?** [*类型*](..\chapter3\03_Types.html#type)
|
||||||
|
> *类型转换运算符* → **as** **!** [*类型*](..\chapter3\03_Types.html#type)
|
||||||
|
|
||||||
<a name="primary_expressions"></a>
|
<a name="primary_expressions"></a>
|
||||||
## 主表达式(Primary Expressions)
|
## 主表达式(Primary Expressions)
|
||||||
@ -211,7 +148,7 @@ let y2: SomeType = x // Type information from an annotation
|
|||||||
|
|
||||||
> 主表达式语法
|
> 主表达式语法
|
||||||
> *主表达式* → [*标识符*](LexicalStructure.html#identifier) [*泛型参数子句*](GenericParametersAndArguments.html#generic_argument_clause) _可选_
|
> *主表达式* → [*标识符*](LexicalStructure.html#identifier) [*泛型参数子句*](GenericParametersAndArguments.html#generic_argument_clause) _可选_
|
||||||
> *主表达式* → [*字面量表达式*](..\chapter3\04_Expressions.html#literal_expression)
|
> *主表达式* → [*字符型表达式*](..\chapter3\04_Expressions.html#literal_expression)
|
||||||
> *主表达式* → [*self表达式*](..\chapter3\04_Expressions.html#self_expression)
|
> *主表达式* → [*self表达式*](..\chapter3\04_Expressions.html#self_expression)
|
||||||
> *主表达式* → [*超类表达式*](..\chapter3\04_Expressions.html#superclass_expression)
|
> *主表达式* → [*超类表达式*](..\chapter3\04_Expressions.html#superclass_expression)
|
||||||
> *主表达式* → [*闭包表达式*](..\chapter3\04_Expressions.html#closure_expression)
|
> *主表达式* → [*闭包表达式*](..\chapter3\04_Expressions.html#closure_expression)
|
||||||
@ -232,18 +169,36 @@ let y2: SomeType = x // Type information from an annotation
|
|||||||
|
|
||||||
在某个函数(function)中,`__FUNCTION__` 会返回当前函数的名字。 在某个方法(method)中,它会返回当前方法的名字。 在某个property 的getter/setter中会返回这个属性的名字。 在特殊的成员如init/subscript中 会返回这个关键字的名字,在某个文件的顶端(the top level of a file),它返回的是当前module的名字。
|
在某个函数(function)中,`__FUNCTION__` 会返回当前函数的名字。 在某个方法(method)中,它会返回当前方法的名字。 在某个property 的getter/setter中会返回这个属性的名字。 在特殊的成员如init/subscript中 会返回这个关键字的名字,在某个文件的顶端(the top level of a file),它返回的是当前module的名字。
|
||||||
|
|
||||||
一个array literal,是一个有序的值的集合。 它的形式是:
|
当作为函数或者方法时,字符型表达式的值在被调用时初始化。
|
||||||
|
```swift
|
||||||
|
func logFunctionName(string: String = __FUNCTION__) {
|
||||||
|
print(string)
|
||||||
|
}
|
||||||
|
func myFunction() {
|
||||||
|
logFunctionName() // Prints "myFunction()".
|
||||||
|
}
|
||||||
|
|
||||||
|
myFunction()
|
||||||
|
namedArgs(1, withJay: 2)
|
||||||
|
```
|
||||||
|
|
||||||
|
一个`array literal`,是一个有序的值的集合。 它的形式是:
|
||||||
|
|
||||||
> [`value 1`, `value 2`, `...`]
|
> [`value 1`, `value 2`, `...`]
|
||||||
|
|
||||||
数组中的最后一个表达式可以紧跟一个逗号(','). []表示空数组 。 array literal的type是 T[], 这个T就是数组中元素的type. 如果该数组中有多种type, T则是跟这些type的公共supertype最接近的type.(closest common supertype)
|
数组中的最后一个表达式可以紧跟一个逗号(','). []表示空数组 。 array literal的type是 T[], 这个T就是数组中元素的type. 如果该数组中有多种type, T则是跟这些type的公共`supertype`最接近的type.空的`array literal`由一组方括号定义,可用来创建特定类型的空数组。
|
||||||
|
```swift
|
||||||
|
var emptyArray: [Double] = []
|
||||||
|
```
|
||||||
|
|
||||||
一个`dictionary literal` 是一个包含无序的键值对(key-value pairs)的集合,它的形式是:
|
一个`dictionary literal` 是一个包含无序的键值对(key-value pairs)的集合,它的形式是:
|
||||||
|
|
||||||
> [`key 1`: `value 1`, `key 2`: `value 2`, `...`]
|
> [`key 1`: `value 1`, `key 2`: `value 2`, `...`]
|
||||||
|
|
||||||
dictionary 的最后一个表达式可以是一个逗号(','). [:] 表示一个空的dictionary. 它的type是 Dictionary<KeyType, ValueType> (这里KeyType表示 key的type, ValueType表示 value的type) 如果这个dictionary 中包含多种 types, 那么KeyType, Value 则对应着它们的公共supertype最接近的type( closest common supertype).
|
dictionary 的最后一个表达式可以是一个逗号(','). [:] 表示一个空的dictionary. 它的type是 Dictionary<KeyType, ValueType> (这里KeyType表示 key的type, ValueType表示 value的type) 如果这个dictionary 中包含多种 types, 那么KeyType, Value 则对应着它们的公共supertype最接近的type( closest common supertype).一个空的dictionary literal由方括号中加一个冒号组成,以此来与空array literal区分开,可以使用空的dictionary literal来创建特定类型的键值对。
|
||||||
|
```swift
|
||||||
|
var emptyDictionary: [String: Double]=[:]
|
||||||
|
```
|
||||||
> 字面量表达式语法
|
> 字面量表达式语法
|
||||||
> *字面量表达式* → [*字面量*](LexicalStructure.html#literal)
|
> *字面量表达式* → [*字面量*](LexicalStructure.html#literal)
|
||||||
> *字面量表达式* → [*数组字面量*](..\chapter3\04_Expressions.html#array_literal) | [*字典字面量*](..\chapter3\04_Expressions.html#dictionary_literal)
|
> *字面量表达式* → [*数组字面量*](..\chapter3\04_Expressions.html#array_literal) | [*字典字面量*](..\chapter3\04_Expressions.html#dictionary_literal)
|
||||||
@ -531,8 +486,7 @@ t.0 = t.1
|
|||||||
// Now t is (20, 20, 30)
|
// Now t is (20, 20, 30)
|
||||||
```
|
```
|
||||||
|
|
||||||
The members of a module access the top-level declarations of that module.
|
对于某个module的member的调用,只能调用在top-level声明中的member.
|
||||||
(不确定:对于某个module的member的调用,只能调用在top-level声明中的member.)
|
|
||||||
|
|
||||||
> 显式成员表达式语法
|
> 显式成员表达式语法
|
||||||
> *显示成员表达式* → [*后置表达式*](..\chapter3\04_Expressions.html#postfix_expression) **.** [*十进制数字*](..\chapter3\02_Lexical_Structure.html#decimal_digit)
|
> *显示成员表达式* → [*后置表达式*](..\chapter3\04_Expressions.html#postfix_expression) **.** [*十进制数字*](..\chapter3\02_Lexical_Structure.html#decimal_digit)
|
||||||
@ -604,6 +558,16 @@ someInstance.dynamicType.printClassName()
|
|||||||
> `expression`!
|
> `expression`!
|
||||||
|
|
||||||
如果该表达式的值不是nil, 则返回对应的值。 否则,抛出运行时错误(runtime error)。
|
如果该表达式的值不是nil, 则返回对应的值。 否则,抛出运行时错误(runtime error)。
|
||||||
|
返回的值可能会被需改,可以是被赋值了,也可以是出现异常造成的。比如:
|
||||||
|
```swift
|
||||||
|
var x: Int? = 0
|
||||||
|
x!++
|
||||||
|
// x is now 1
|
||||||
|
|
||||||
|
var someDictionary = ["a": [1, 2, 3], "b": [10, 20]]
|
||||||
|
someDictionary["a"]![0] = 100
|
||||||
|
// someDictionary is now [b: [10, 20], a: [100, 2, 3]]
|
||||||
|
```
|
||||||
|
|
||||||
> 强制取值(Forced Value)语法
|
> 强制取值(Forced Value)语法
|
||||||
> *强制取值(Forced Value)表达式* → [*后置表达式*](..\chapter3\04_Expressions.html#postfix_expression) **!**
|
> *强制取值(Forced Value)表达式* → [*后置表达式*](..\chapter3\04_Expressions.html#postfix_expression) **!**
|
||||||
@ -632,6 +596,22 @@ if let unwrappedC = c {
|
|||||||
result = unwrappedC.property.performAction()
|
result = unwrappedC.property.performAction()
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
后缀'?' 返回目标表达式的值可能会被修改,可能是由于出现了赋值,也有可能是出现异常而产生的修改。如果可选链表达式为`nil`,则表达式右边的复制操作不会被执行。比如:
|
||||||
|
```swift
|
||||||
|
func someFunctionWithSideEffects() -> Int {
|
||||||
|
return 42 // No actual side effects.
|
||||||
|
}
|
||||||
|
var someDictionary = ["a": [1, 2, 3], "b": [10, 20]]
|
||||||
|
|
||||||
|
someDictionary["not here"]?[0] = someFunctionWithSideEffects()
|
||||||
|
// someFunctionWithSideEffects is not evaluated
|
||||||
|
// someDictionary is still [b: [10, 20], a: [1, 2, 3]]
|
||||||
|
|
||||||
|
someDictionary["a"]?[0] = someFunctionWithSideEffects()
|
||||||
|
// someFunctionWithSideEffects is evaluated and returns 42
|
||||||
|
// someDictionary is now [b: [10, 20], a: [42, 2, 3]]
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
> 可选链表达式语法
|
> 可选链表达式语法
|
||||||
> *可选链表达式* → [*后置表达式*](..\chapter3\04_Expressions.html#postfix_expression) **?**
|
> *可选链表达式* → [*后置表达式*](..\chapter3\04_Expressions.html#postfix_expression) **?**
|
||||||
|
|||||||
Reference in New Issue
Block a user