19,type casting ,for 3.0.1
This commit is contained in:
@ -1,4 +1,4 @@
|
|||||||
# 类型转换(Type Casting)
|
# 类型转换
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
> 1.0
|
> 1.0
|
||||||
@ -13,12 +13,13 @@
|
|||||||
>
|
>
|
||||||
> 2.2
|
> 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)
|
- [定义一个类层次作为例子](#defining_a_class_hierarchy_for_type_casting)
|
||||||
- [检查类型](#checking_type)
|
- [检查类型](#checking_type)
|
||||||
- [向下转型(Downcasting)](#downcasting)
|
- [向下转型](#downcasting)
|
||||||
- [`Any` 和 `AnyObject` 的类型转换](#type_casting_for_any_and_anyobject)
|
- [`Any` 和 `AnyObject` 的类型转换](#type_casting_for_any_and_anyobject)
|
||||||
|
|
||||||
|
|
||||||
@ -80,7 +81,7 @@ let library = [
|
|||||||
在幕后 `library` 里存储的媒体项依然是 `Movie` 和 `Song` 类型的。但是,若你迭代它,依次取出的实例会是 `MediaItem` 类型的,而不是 `Movie` 和 `Song` 类型。为了让它们作为原本的类型工作,你需要检查它们的类型或者向下转换它们到其它类型,就像下面描述的一样。
|
在幕后 `library` 里存储的媒体项依然是 `Movie` 和 `Song` 类型的。但是,若你迭代它,依次取出的实例会是 `MediaItem` 类型的,而不是 `Movie` 和 `Song` 类型。为了让它们作为原本的类型工作,你需要检查它们的类型或者向下转换它们到其它类型,就像下面描述的一样。
|
||||||
|
|
||||||
<a name="checking_type"></a>
|
<a name="checking_type"></a>
|
||||||
## 检查类型(Checking Type)
|
## 检查类型
|
||||||
|
|
||||||
用类型检查操作符(`is`)来检查一个实例是否属于特定子类型。若实例属于那个子类型,类型检查操作符返回 `true`,否则返回 `false`。
|
用类型检查操作符(`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` 的值就是被找到的属于各自类型的实例的数量。
|
`true`,否则返回 `false`。同样的,`item is Song` 检查 `item` 是否为 `Song` 类型的实例。在循环结束后,`movieCount` 和 `songCount` 的值就是被找到的属于各自类型的实例的数量。
|
||||||
|
|
||||||
<a name="downcasting"></a>
|
<a name="downcasting"></a>
|
||||||
## 向下转型(Downcasting)
|
## 向下转型
|
||||||
|
|
||||||
某类型的一个常量或变量可能在幕后实际上属于一个子类。当确定是这种情况时,你可以尝试向下转到它的子类型,用类型转换操作符(`as?` 或 `as!`)。
|
某类型的一个常量或变量可能在幕后实际上属于一个子类。当确定是这种情况时,你可以尝试向下转到它的子类型,用*类型转换操作符*(`as?` 或 `as!`)。
|
||||||
|
|
||||||
因为向下转型可能会失败,类型转型操作符带有两种不同形式。条件形式(conditional form)`as?` 返回一个你试图向下转成的类型的可选值(optional value)。强制形式 `as!` 把试图向下转型和强制解包(force-unwraps)转换结果结合为一个操作。
|
因为向下转型可能会失败,类型转型操作符带有两种不同形式。条件形式`as?` 返回一个你试图向下转成的类型的可选值。强制形式 `as!` 把试图向下转型和强制解包(转换结果结合为一个操作。
|
||||||
|
|
||||||
当你不确定向下转型可以成功时,用类型转换的条件形式(`as?`)。条件形式的类型转换总是返回一个可选值(optional value),并且若下转是不可能的,可选值将是 `nil`。这使你能够检查向下转型是否成功。
|
当你不确定向下转型可以成功时,用类型转换的条件形式(`as?`)。条件形式的类型转换总是返回一个可选值,并且若下转是不可能的,可选值将是 `nil`。这使你能够检查向下转型是否成功。
|
||||||
|
|
||||||
只有你可以确定向下转型一定会成功时,才使用强制形式(`as!`)。当你试图向下转型为一个不正确的类型时,强制形式的类型转换会触发一个运行时错误。
|
只有你可以确定向下转型一定会成功时,才使用强制形式(`as!`)。当你试图向下转型为一个不正确的类型时,强制形式的类型转换会触发一个运行时错误。
|
||||||
|
|
||||||
@ -158,55 +159,10 @@ for item in library {
|
|||||||
|
|
||||||
Swift 为不确定类型提供了两种特殊的类型别名:
|
Swift 为不确定类型提供了两种特殊的类型别名:
|
||||||
|
|
||||||
* `AnyObject` 可以表示任何类类型的实例。
|
|
||||||
* `Any` 可以表示任何类型,包括函数类型。
|
* `Any` 可以表示任何类型,包括函数类型。
|
||||||
|
* `AnyObject` 可以表示任何类类型的实例。
|
||||||
|
|
||||||
> 注意
|
只有当你确实需要它们的行为和功能时才使用 `Any` 和 `AnyObject`。在你的代码里使用你期望的明确类型总是更好的。
|
||||||
> 只有当你确实需要它们的行为和功能时才使用 `Any` 和 `AnyObject`。在你的代码里使用你期望的明确类型总是更好的。
|
|
||||||
|
|
||||||
<a name="anyobject"></a>
|
|
||||||
### `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
|
|
||||||
```
|
|
||||||
|
|
||||||
<a name="any"></a>
|
|
||||||
### `Any` 类型
|
|
||||||
|
|
||||||
这里有个示例,使用 `Any` 类型来和混合的不同类型一起工作,包括函数类型和非类类型。它创建了一个可以存储 `Any` 类型的数组 `things`:
|
这里有个示例,使用 `Any` 类型来和混合的不同类型一起工作,包括函数类型和非类类型。它创建了一个可以存储 `Any` 类型的数组 `things`:
|
||||||
|
|
||||||
@ -262,3 +218,12 @@ for thing in things {
|
|||||||
// a movie called 'Ghostbusters', dir. Ivan Reitman
|
// a movie called 'Ghostbusters', dir. Ivan Reitman
|
||||||
// Hello, Michael
|
// Hello, Michael
|
||||||
```
|
```
|
||||||
|
|
||||||
|
> 注意
|
||||||
|
> `Any`类型可以表示所有类型的值,包括可选类型。Swift 会在你用`Any`类型来表示一个可选值的时候,给你一个警告。如果你确实想使用`Any`类型来承载可选值,你可以使用`as`操作符显示转换为`Any`,如下所示:
|
||||||
|
>
|
||||||
|
```swift
|
||||||
|
let optionalNumber: Int? = 3
|
||||||
|
things.append(optionalNumber) // 警告
|
||||||
|
things.append(optionalNumber as Any) // 没有警告
|
||||||
|
```
|
||||||
|
|||||||
Reference in New Issue
Block a user