From dc3b19aa6f4098f9e633633b257999a7bb8cb43d Mon Sep 17 00:00:00 2001 From: shanks Date: Sun, 13 Nov 2016 15:42:51 +0800 Subject: [PATCH] 19,type casting ,for 3.0.1 --- source/chapter2/19_Type_Casting.md | 75 ++++++++---------------------- 1 file changed, 20 insertions(+), 55 deletions(-) diff --git a/source/chapter2/19_Type_Casting.md b/source/chapter2/19_Type_Casting.md index 8eef424b..8ddd57ff 100644 --- a/source/chapter2/19_Type_Casting.md +++ b/source/chapter2/19_Type_Casting.md @@ -1,4 +1,4 @@ -# 类型转换(Type Casting) +# 类型转换 ----------------- > 1.0 @@ -12,13 +12,14 @@ > 校对:[shanks](http://codebuild.me),2015-11-01 > > 2.2 -> 翻译+校对:[SketchK](https://github.com/SketchK) 2016-05-16 +> 翻译+校对:[SketchK](https://github.com/SketchK) 2016-05-16 +> 3.0.1,shanks,2016-11-13 本页包含内容: - [定义一个类层次作为例子](#defining_a_class_hierarchy_for_type_casting) - [检查类型](#checking_type) -- [向下转型(Downcasting)](#downcasting) +- [向下转型](#downcasting) - [`Any` 和 `AnyObject` 的类型转换](#type_casting_for_any_and_anyobject) @@ -80,7 +81,7 @@ let library = [ 在幕后 `library` 里存储的媒体项依然是 `Movie` 和 `Song` 类型的。但是,若你迭代它,依次取出的实例会是 `MediaItem` 类型的,而不是 `Movie` 和 `Song` 类型。为了让它们作为原本的类型工作,你需要检查它们的类型或者向下转换它们到其它类型,就像下面描述的一样。 -## 检查类型(Checking Type) +## 检查类型 用类型检查操作符(`is`)来检查一个实例是否属于特定子类型。若实例属于那个子类型,类型检查操作符返回 `true`,否则返回 `false`。 @@ -109,13 +110,13 @@ print("Media library contains \(movieCount) movies and \(songCount) songs") `true`,否则返回 `false`。同样的,`item is Song` 检查 `item` 是否为 `Song` 类型的实例。在循环结束后,`movieCount` 和 `songCount` 的值就是被找到的属于各自类型的实例的数量。 -## 向下转型(Downcasting) +## 向下转型 -某类型的一个常量或变量可能在幕后实际上属于一个子类。当确定是这种情况时,你可以尝试向下转到它的子类型,用类型转换操作符(`as?` 或 `as!`)。 +某类型的一个常量或变量可能在幕后实际上属于一个子类。当确定是这种情况时,你可以尝试向下转到它的子类型,用*类型转换操作符*(`as?` 或 `as!`)。 -因为向下转型可能会失败,类型转型操作符带有两种不同形式。条件形式(conditional form)`as?` 返回一个你试图向下转成的类型的可选值(optional value)。强制形式 `as!` 把试图向下转型和强制解包(force-unwraps)转换结果结合为一个操作。 +因为向下转型可能会失败,类型转型操作符带有两种不同形式。条件形式`as?` 返回一个你试图向下转成的类型的可选值。强制形式 `as!` 把试图向下转型和强制解包(转换结果结合为一个操作。 -当你不确定向下转型可以成功时,用类型转换的条件形式(`as?`)。条件形式的类型转换总是返回一个可选值(optional value),并且若下转是不可能的,可选值将是 `nil`。这使你能够检查向下转型是否成功。 +当你不确定向下转型可以成功时,用类型转换的条件形式(`as?`)。条件形式的类型转换总是返回一个可选值,并且若下转是不可能的,可选值将是 `nil`。这使你能够检查向下转型是否成功。 只有你可以确定向下转型一定会成功时,才使用强制形式(`as!`)。当你试图向下转型为一个不正确的类型时,强制形式的类型转换会触发一个运行时错误。 @@ -158,55 +159,10 @@ for item in library { Swift 为不确定类型提供了两种特殊的类型别名: -* `AnyObject` 可以表示任何类类型的实例。 * `Any` 可以表示任何类型,包括函数类型。 +* `AnyObject` 可以表示任何类类型的实例。 -> 注意 -> 只有当你确实需要它们的行为和功能时才使用 `Any` 和 `AnyObject`。在你的代码里使用你期望的明确类型总是更好的。 - - -### `AnyObject` 类型 - -当我们使用 Cocoa APIs 时,我们会接收到一个 `[AnyObject]` 类型的数组,或者说“一个任意类型对象的数组”。Objective-C现在支持明确的数组类型,但早期版本的Objective-C并没有这个功能。不管怎样,你都可以确信API提供的信息能够正确的表明数组中的元素类型。 - - -在这些情况下,你可以使用强制形式的类型转换(`as!`)来下转数组中的每一项到比 `AnyObject` 更明确的类型,不需要可选解包(optional unwrapping)。 - -下面的示例定义了一个 `[AnyObject]` 类型的数组并填入三个 `Movie` 类型的实例: - -```swift -let someObjects: [AnyObject] = [ - Movie(name: "2001: A Space Odyssey", director: "Stanley Kubrick"), - Movie(name: "Moon", director: "Duncan Jones"), - Movie(name: "Alien", director: "Ridley Scott") -] -``` - -因为知道这个数组只包含 `Movie` 实例,你可以直接用(`as!`)下转并解包到非可选的 `Movie` 类型: - -```swift -for object in someObjects { - let movie = object as! Movie - print("Movie: '\(movie.name)', dir. \(movie.director)") -} -// Movie: '2001: A Space Odyssey', dir. Stanley Kubrick -// Movie: 'Moon', dir. Duncan Jones -// Movie: 'Alien', dir. Ridley Scott -``` - -为了变为一个更简短的形式,下转 `someObjects` 数组为 `[Movie]` 类型而不是下转数组中的每一项: - -```swift -for movie in someObjects as! [Movie] { - print("Movie: '\(movie.name)', dir. \(movie.director)") -} -// Movie: '2001: A Space Odyssey', dir. Stanley Kubrick -// Movie: 'Moon', dir. Duncan Jones -// Movie: 'Alien', dir. Ridley Scott -``` - - -### `Any` 类型 +只有当你确实需要它们的行为和功能时才使用 `Any` 和 `AnyObject`。在你的代码里使用你期望的明确类型总是更好的。 这里有个示例,使用 `Any` 类型来和混合的不同类型一起工作,包括函数类型和非类类型。它创建了一个可以存储 `Any` 类型的数组 `things`: @@ -262,3 +218,12 @@ for thing in things { // a movie called 'Ghostbusters', dir. Ivan Reitman // Hello, Michael ``` + +> 注意 +> `Any`类型可以表示所有类型的值,包括可选类型。Swift 会在你用`Any`类型来表示一个可选值的时候,给你一个警告。如果你确实想使用`Any`类型来承载可选值,你可以使用`as`操作符显示转换为`Any`,如下所示: +> +```swift +let optionalNumber: Int? = 3 +things.append(optionalNumber) // 警告 +things.append(optionalNumber as Any) // 没有警告 +```