Merge pull request #168 from yulingtianxia/develop

update optional chaining
This commit is contained in:
梁杰
2014-06-14 00:15:07 +08:00
2 changed files with 31 additions and 31 deletions

View File

@ -14,17 +14,17 @@
- [通过可选链调用方法](#calling_methods_through_optional_chaining) - [通过可选链调用方法](#calling_methods_through_optional_chaining)
- [使用可选链调用子脚本](#calling_subscripts_through_optional_chaining) - [使用可选链调用子脚本](#calling_subscripts_through_optional_chaining)
- [连接多层链接](#linking_multiple_levels_of_chaining) - [连接多层链接](#linking_multiple_levels_of_chaining)
- [链接自判断返回值的方法](#chaining_on_methods_with_optional_return_values) - [链接可选返回值的方法](#chaining_on_methods_with_optional_return_values)
可选链Optional Chaining是一种可以请求和调用属性、方法及子脚本的过程它的自判断性体现于请求或调用的目标当前可能为空(`nil`)。如果自判断的目标有值,那么调用就会成功;相反,如果选择的目标为空(`nil`),则这种调用将返回空(`nil`)。多次请求或调用可以被链接在一起形成一个链,如果任何一个节点为空(`nil`)将导致整个链失效。 可选链Optional Chaining是一种可以请求和调用属性、方法及子脚本的过程它的可选性体现于请求或调用的目标当前可能为空(`nil`)。如果可选的目标有值,那么调用就会成功;相反,如果选择的目标为空(`nil`),则这种调用将返回空(`nil`)。多次请求或调用可以被链接在一起形成一个链,如果任何一个节点为空(`nil`)将导致整个链失效。
> 注意: > 注意:
Swift 的自判断链和 Objective-C 中的消息为空有些相像,但是 Swift 可以使用在任意类型中,并且失败与否可以被检测到。 Swift 的可选链和 Objective-C 中的消息为空有些相像,但是 Swift 可以使用在任意类型中,并且失败与否可以被检测到。
<a name="optional_chaining_as_an_alternative_to_forced_unwrapping"></a> <a name="optional_chaining_as_an_alternative_to_forced_unwrapping"></a>
## 可选链可替代强制解析 ## 可选链可替代强制解析
通过在想调用的属性、方法、或子脚本的可选值(`optional value`)(非空)后面放一个问号,可以定义一个可选链。这一点很像在可选值后面放一个声明符号来强制拆得其封包内的值。他们的主要的区别在于当可选值为空时可选链即刻失败,然而一般的强制解析将会引发运行时错误。 通过在想调用的属性、方法、或子脚本的可选值(`optional value`)(非空)后面放一个问号,可以定义一个可选链。这一点很像在可选值后面放一个号来强制拆得其封包内的值。他们的主要的区别在于当可选值为空时可选链即刻失败,然而一般的强制解析将会引发运行时错误。
为了反映可选链可以调用空(`nil`不论你调用的属性、方法、子脚本等返回的值是不是可选值它的返回结果都是一个可选值。你可以利用这个返回值来检测你的可选链是否调用成功有返回值即成功返回nil则失败。 为了反映可选链可以调用空(`nil`不论你调用的属性、方法、子脚本等返回的值是不是可选值它的返回结果都是一个可选值。你可以利用这个返回值来检测你的可选链是否调用成功有返回值即成功返回nil则失败。
@ -42,9 +42,9 @@ Swift 的自判断链和 Objective-C 中的消息为空有些相像,但是 Swi
var numberOfRooms = 1 var numberOfRooms = 1
} }
`Residence`具有一个`Int`类型的`numberOfRooms`,其值为 1。`Person`具有一个自判断`residence`属性,它的类型是`Residence` `Residence`具有一个`Int`类型的`numberOfRooms`,其值为 1。`Person`具有一个可选`residence`属性,它的类型是`Residence`
如果你创建一个新的`Person`实例,它的`residence`属性由于是被定义为自判断型的,此属性将默认初始化为空: 如果你创建一个新的`Person`实例,它的`residence`属性由于是被定义为可选型的,此属性将默认初始化为空:
let john = Person() let john = Person()
@ -64,11 +64,11 @@ Swift 的自判断链和 Objective-C 中的消息为空有些相像,但是 Swi
// 打印 "Unable to retrieve the number of rooms. // 打印 "Unable to retrieve the number of rooms.
这告诉 Swift 来链接自判断`residence?`属性,如果`residence`存在则取回`numberOfRooms`的值。 这告诉 Swift 来链接可选`residence?`属性,如果`residence`存在则取回`numberOfRooms`的值。
因为这种尝试获得`numberOfRooms`的操作有可能失败,可选链会返回`Int?`类型值,或者称作“自判断`Int`”。当`residence`是空的时候(上例),选择`Int`将会为空,因此会出先无法访问`numberOfRooms`的情况。 因为这种尝试获得`numberOfRooms`的操作有可能失败,可选链会返回`Int?`类型值,或者称作“可选`Int`”。当`residence`是空的时候(上例),选择`Int`将会为空,因此会出先无法访问`numberOfRooms`的情况。
要注意的是即使numberOfRooms是非自判断`Int``Int?`)时这一点也成立。只要是通过可选链的请求就意味着最后`numberOfRooms`总是返回一个`Int?`而不是`Int` 要注意的是即使numberOfRooms是非可选`Int``Int?`)时这一点也成立。只要是通过可选链的请求就意味着最后`numberOfRooms`总是返回一个`Int?`而不是`Int`
你可以自己定义一个`Residence`实例给`john.residence`,这样它就不再为空了: 你可以自己定义一个`Residence`实例给`john.residence`,这样它就不再为空了:
@ -118,7 +118,7 @@ Swift 的自判断链和 Objective-C 中的消息为空有些相像,但是 Swi
`Residence`中也提供了一个`printNumberOfRooms`的方法,即简单的打印房间个数。 `Residence`中也提供了一个`printNumberOfRooms`的方法,即简单的打印房间个数。
最后,`Residence`定义了一个自判断属性叫`address``address?`)。`Address`类的属性将在后面定义。 最后,`Residence`定义了一个可选属性叫`address``address?`)。`Address`类的属性将在后面定义。
用于`rooms`数组的`Room`类是一个很简单的类,它只有一个`name`属性和一个设定`room`名的初始化器。 用于`rooms`数组的`Room`类是一个很简单的类,它只有一个`name`属性和一个设定`room`名的初始化器。
class Room { class Room {
@ -127,7 +127,7 @@ Swift 的自判断链和 Objective-C 中的消息为空有些相像,但是 Swi
} }
这个模型中的最终类叫做`Address`。它有三个自判断属性他们额类型是`String?`。前面两个自判断属性`buildingName``buildingNumber`作为地址的一部分,是定义某个建筑物的两种方式。第三个属性`street`,用于命名地址的街道名: 这个模型中的最终类叫做`Address`。它有三个类型是`String?`的可选属性。前面两个可选属性`buildingName``buildingNumber`作为地址的一部分,是定义某个建筑物的两种方式。第三个属性`street`,用于命名地址的街道名:
class Address { class Address {
var buildingName: String? var buildingName: String?
@ -176,7 +176,7 @@ Swift 的自判断链和 Objective-C 中的消息为空有些相像,但是 Swi
这个方法没有返回值。但是,没有返回值类型的函数和方法有一个隐式的返回值类型`Void`参见Function Without Return Values 这个方法没有返回值。但是,没有返回值类型的函数和方法有一个隐式的返回值类型`Void`参见Function Without Return Values
如果你利用可选链调用此方法,这个方法的返回值类型将是`Void?`,而不是`Void`因为当通过可选链调用方法时返回值总是可选类型optional type即使这个方法本没有定义返回值,你也可以使用`if`语句来检查是否能成功调用`printNumberOfRooms`方法:如果方法通过可选链调用成功,`printNumberOfRooms`的隐式返回值将会是`Void`,如果没有成功,将返回`nil` 如果你利用可选链调用此方法,这个方法的返回值类型将是`Void?`,而不是`Void`因为当通过可选链调用方法时返回值总是可选类型optional type。即使这个方法本没有定义返回值,你也可以使用`if`语句来检查是否能成功调用`printNumberOfRooms`方法:如果方法通过可选链调用成功,`printNumberOfRooms`的隐式返回值将会是`Void`,如果没有成功,将返回`nil`
if john.residence?.printNumberOfRooms() { if john.residence?.printNumberOfRooms() {
println("It was possible to print the number of rooms.") println("It was possible to print the number of rooms.")
@ -191,7 +191,7 @@ Swift 的自判断链和 Objective-C 中的消息为空有些相像,但是 Swi
你可以使用可选链来尝试从子脚本获取值并检查子脚本的调用是否成功,然而,你不能通过可选链来设置子代码。 你可以使用可选链来尝试从子脚本获取值并检查子脚本的调用是否成功,然而,你不能通过可选链来设置子代码。
> 注意: > 注意:
当你使用可选链来获取子脚本的时候,你应该将问号放在子脚本括号的前面而不是后面。可选链的问号一般直接跟在自判断表达语句的后面。 当你使用可选链来获取子脚本的时候,你应该将问号放在子脚本括号的前面而不是后面。可选链的问号一般直接跟在表达语句的后面。
下面这个例子用在`Residence`类中定义的子脚本来获取`john.residence`数组中第一个房间的名字。因为`john.residence`现在是`nil`,子脚本的调用失败了。 下面这个例子用在`Residence`类中定义的子脚本来获取`john.residence`数组中第一个房间的名字。因为`john.residence`现在是`nil`,子脚本的调用失败了。
@ -225,7 +225,7 @@ Swift 的自判断链和 Objective-C 中的消息为空有些相像,但是 Swi
也就是说: 也就是说:
如果你试图获得的类型不是可选类型,由于使用了可选链它将变成可选类型。 如果你试图获得的类型不是可选类型,由于使用了可选链它将变成可选类型。
如果你试图获得的类型已经是可选类型,由于可选链它也不会提高自判断性。 如果你试图获得的类型已经是可选类型,由于可选链它也不会提高可选性。
因此: 因此:
@ -259,12 +259,12 @@ Swift 的自判断链和 Objective-C 中的消息为空有些相像,但是 Swi
} }
// 打印 "John's street name is Laurel Street."。 // 打印 "John's street name is Laurel Street."。
值得注意的是,“`!`”符的在定义`address`实例时的使用(`john.residence.address``john.residence`属性是一个可选类型,因此你需要在它获取`address`属性之前使用`!`解析以获得它的实际值。 值得注意的是,“`!`”符号在给`john.residence.address`分配`address`实例时的使用`john.residence`属性是一个可选类型,因此你需要在它获取`address`属性之前使用`!`解析以获得它的实际值。
<a name="chaining_on_methods_with_optional_return_values"></a> <a name="chaining_on_methods_with_optional_return_values"></a>
##链接自判断返回值的方法 ##链接可选返回值的方法
前面的例子解释了如何通过可选链来获得可选类型属性值。你也可以通过调用返回可选类型值的方法并按需链接方法的返回值。 前面的例子解释了如何通过可选链来获得可选类型属性值。你也可以通过可选链调用一个返回可选类型值的方法并按需链接方法的返回值。
下面的例子通过可选链调用了`Address`类中的`buildingIdentifier` 方法。这个方法的返回值类型是`String?`。如上所述,这个方法在可选链调用后最终的返回值类型依然是`String?` 下面的例子通过可选链调用了`Address`类中的`buildingIdentifier` 方法。这个方法的返回值类型是`String?`。如上所述,这个方法在可选链调用后最终的返回值类型依然是`String?`

View File

@ -2,7 +2,7 @@
> 校对happyming > 校对happyming
# 类型检查Type Casting # 类型转换Type Casting
----------------- -----------------
本页包含内容: 本页包含内容:
@ -10,14 +10,14 @@
- [定义一个类层次作为例子](#defining_a_class_hierarchy_for_type_casting) - [定义一个类层次作为例子](#defining_a_class_hierarchy_for_type_casting)
- [检查类型](#checking_type) - [检查类型](#checking_type)
- [向下转型Downcasting](#downcasting) - [向下转型Downcasting](#downcasting)
- [`Any`和`AnyObject`的类型检查](#type_casting_for_any_and_anyobject) - [`Any`和`AnyObject`的类型转换](#type_casting_for_any_and_anyobject)
_类型检查_是一种检查类实例的方式并且或者也是让实例作为它的父类或者子类的一种方式。 _类型检查_是一种检查类实例的方式并且或者也是让实例作为它的父类或者子类的一种方式。
类型检查在 Swift 中使用`is``as`操作符实现。这两个操作符提供了一种简单达意的方式去检查值的类型或者转换它的类型。 类型检查在 Swift 中使用`is``as`操作符实现。这两个操作符提供了一种简单达意的方式去检查值的类型或者转换它的类型。
你也可以用来检查一个类是否实现了某个协议,就像在 [Protocols Checking for Protocol Conformance](Protocols.html#//apple_ref/doc/uid/TP40014097-CH25-XID_363)部分讲述的一样。 你也可以用来检查一个类是否实现了某个协议,就像在 [Checking for Protocol Conformance](Protocols.html#//apple_ref/doc/uid/TP40014097-CH25-XID_363)部分讲述的一样。
<a name="defining_a_class_hierarchy_for_type_casting"></a> <a name="defining_a_class_hierarchy_for_type_casting"></a>
## 定义一个类层次作为例子 ## 定义一个类层次作为例子
@ -68,7 +68,7 @@
<a name="checking_type"></a> <a name="checking_type"></a>
## 检查类型 ## 检查类型
用类型检查操作符(`is`)来检查一个实例是否属于特定子类型。类型检查操作符返回 `true` 若实例属于那个子类型,若不属于返回 `false` 用类型检查操作符(`is`)来检查一个实例是否属于特定子类型。若实例属于那个子类型,类型检查操作符返回 `true` ,否则返回 `false`
下面的例子定义了两个变量,`movieCount``songCount`,用来计算数组`library``Movie``Song` 类型的实例数量。 下面的例子定义了两个变量,`movieCount``songCount`,用来计算数组`library``Movie``Song` 类型的实例数量。
@ -96,17 +96,17 @@
<a name="downcasting"></a> <a name="downcasting"></a>
## 向下转型Downcasting ## 向下转型Downcasting
某类型的一个常量或变量可能在幕后实际上属于一个子类。你可以相信,上面就是这种情况。你可以尝试向下转到它的子类型,用类型检查操作符(`as`) 某类型的一个常量或变量可能在幕后实际上属于一个子类。你可以相信,上面就是这种情况。你可以尝试向下转到它的子类型,用类型转换操作符(`as`)
因为向下转型可能会失败,类型检查操作符带有两种不同形式。可选形式( optional form `as?` 返回一个你试图下转成的类型的可选值optional value。强制形式 `as` 把试图向下转型和强制解包force-unwraps结果作为一个混合动作。 因为向下转型可能会失败,类型转型操作符带有两种不同形式。可选形式( optional form `as?` 返回一个你试图下转成的类型的可选值optional value。强制形式 `as` 把试图向下转型和强制解包force-unwraps结果作为一个混合动作。
当你不确定下转可以成功时,用类型检查的可选形式(`as?`)。可选形式的类型检查总是返回一个可选值optional value并且若下转是不可能的可选值将是 `nil` 。这使你能够检查下转是否成功。 当你不确定下转可以成功时,用类型转换的可选形式(`as?`)。可选形式的类型转换总是返回一个可选值optional value并且若下转是不可能的可选值将是 `nil` 。这使你能够检查下转是否成功。
只有你可以确定下转一定会成功时,才使用强制形式。当你试图下转为一个不正确的类型时,强制形式的类型检查会触发一个运行时错误。 只有你可以确定下转一定会成功时,才使用强制形式。当你试图下转为一个不正确的类型时,强制形式的类型转换会触发一个运行时错误。
下面的例子,迭代了`library`里的每一个 `MediaItem` ,并打印出适当的描述。要这样做,`item`需要真正作为`Movie``Song`的类型来使用。不仅仅是作为 `MediaItem`。为了能够使用`Movie``Song``director``artist`属性,这是必要的。 下面的例子,迭代了`library`里的每一个 `MediaItem` ,并打印出适当的描述。要这样做,`item`需要真正作为`Movie``Song`的类型来使用。不仅仅是作为 `MediaItem`。为了能够使用`Movie``Song``director``artist`属性,这是必要的。
在这个示例中,数组中的每一个`item`可能是 `Movie``Song`。 事前你不知道每个`item`的真实类型,所以这里使用可选形式的类型检查 `as?`)去检查循环里的每次下转。 在这个示例中,数组中的每一个`item`可能是 `Movie``Song`。 事前你不知道每个`item`的真实类型,所以这里使用可选形式的类型转换 `as?`)去检查循环里的每次下转。
for item in library { for item in library {
if let movie = item as? Movie { if let movie = item as? Movie {
@ -126,19 +126,19 @@
类型的实例,它可能是一个`Movie`;同样,它可能是一个 `Song`,或者仅仅是基类 类型的实例,它可能是一个`Movie`;同样,它可能是一个 `Song`,或者仅仅是基类
`MediaItem`。因为不确定,`as?`形式在试图下转时将返还一个可选值。 `item as Movie` 的返回值是`Movie?`类型或 “optional `Movie`”。 `MediaItem`。因为不确定,`as?`形式在试图下转时将返还一个可选值。 `item as Movie` 的返回值是`Movie?`类型或 “optional `Movie`”。
当下转为 `Movie` 应用在两个 `Song` 下转`Movie` 应用在两个 `Song`
实例时将会失败。为了处理这种情况上面的例子使用了可选绑定optional binding来检查可选 `Movie`真的包含一个值(这个是为了判断下转是否成功。)可选绑定是这样写的“`if let movie = item as? Movie`”,可以这样解读: 实例时将会失败。为了处理这种情况上面的例子使用了可选绑定optional binding来检查可选 `Movie`真的包含一个值(这个是为了判断下转是否成功。)可选绑定是这样写的“`if let movie = item as? Movie`”,可以这样解读:
“尝试将 `item` 转为 `Movie`类型。若成功,设置一个新的临时常量 `movie` 来存储返回的可选`Movie` “尝试将 `item` 转为 `Movie`类型。若成功,设置一个新的临时常量 `movie` 来存储返回的可选`Movie`
若下转成功,然后`movie`的属性将用于打印一个`Movie`实例的描述,包括它的导演的名字`director`。当`Song`被找到时,一个相近的原理被用来检测 `Song` 实例和打印它的描述。 下转成功,然后`movie`的属性将用于打印一个`Movie`实例的描述,包括它的导演的名字`director`。当`Song`被找到时,一个相近的原理被用来检测 `Song` 实例和打印它的描述。
> 注意: > 注意:
> >
转换没有真的改变实例或它的值。潜在的根本的实例保持不变;只是简单地把它作为它被转换成的类来使用。 转换没有真的改变实例或它的值。潜在的根本的实例保持不变;只是简单地把它作为它被转换成的类来使用。
<a name="type_casting_for_any_and_anyobject"></a> <a name="type_casting_for_any_and_anyobject"></a>
## `Any`和`AnyObject`的类型检查 ## `Any`和`AnyObject`的类型转换
Swift为不确定类型提供了两种特殊类型别名 Swift为不确定类型提供了两种特殊类型别名
@ -155,7 +155,7 @@
当需要在工作中使用 Cocoa 当需要在工作中使用 Cocoa
APIs它一般接收一个`AnyObject[]`类型的数组,或者说“一个任何对象类型的数组”。这是因为 Objective-C 没有明确的类型化数组。但是,你常常可以确定包含在仅从你知道的 API 信息提供的这样一个数组中的对象的类型。 APIs它一般接收一个`AnyObject[]`类型的数组,或者说“一个任何对象类型的数组”。这是因为 Objective-C 没有明确的类型化数组。但是,你常常可以确定包含在仅从你知道的 API 信息提供的这样一个数组中的对象的类型。
在这些情况下,你可以使用强制形式的类型检查(`as`)来下转在数组中的每一项到比 `AnyObject` 更明确的类型不需要可选解析optional unwrapping 在这些情况下,你可以使用强制形式的类型转换(`as`)来下转在数组中的每一项到比 `AnyObject` 更明确的类型不需要可选解析optional unwrapping
下面的示例定义了一个 `AnyObject[]` 类型的数组并填入三个`Movie`类型的实例: 下面的示例定义了一个 `AnyObject[]` 类型的数组并填入三个`Movie`类型的实例:
@ -236,4 +236,4 @@
> 注意: > 注意:
> >
在一个switch语句的case中使用强制形式的类型检查操作符as, 而不是 as?)来检查和转换到一个明确的类型。在 switch case 语句的内容中这种检查总是安全的。 在一个switch语句的case中使用强制形式的类型转换操作符as, 而不是 as?)来检查和转换到一个明确的类型。在 switch case 语句的内容中这种检查总是安全的。