由于是多人协同翻译,可能会有些术语或者句子翻译不太恰当,如果您在阅读过程中发现此类问题,请直接给我们提 issue 或者 pull request。翻译完成后我们会进行认真的校对,给大家提供一本高质量的 Swift 教程。
如果您愿意加入进来,帮助我们进行翻译和校对,请阅读[项目首页](https://github.com/numbbbbb/the-swift-programming-language-in-chinese)中的说明并加入QQ群:364279588,我们期待您的加入,在 Swift 的历史上留下您的足迹!
`SomeType(ofInitialValue)`是调用 Swift 构造器并传入一个初始值的默认方法。在语言内部,`UInt16`有一个构造器,可以接受一个`UInt8`类型的值,所以这个构造器可以用现有的`UInt8`来创建一个新的`UInt16`。注意,你并不能传入任意类型的值,只能传入`UInt16`内部有对应构造器的值。不过你可以扩展现有的类型来让它可以接收其他类型的值(包括自定义类型),详情参见`扩展(链接待添加)`.
@ -292,18 +275,18 @@ Swift 是类型安全的,会在编译你的代码时进行类型检查,如
@ -327,7 +310,7 @@ Swift 有一个基本的布尔类型,叫做`Bool`。布尔值是指逻辑,
let orangesAreOrange = true
let turnipsAreDelicious = false
`orangesAreOrange`和`turnipsAreDelicious`的类型会被推导为`Bool`,因为它们的初值是布尔原始值。就像之前提到的`Int`和`Double`一样,如果你创建变量的时候给它们赋值`true`或者`false`,那你不需要给常量或者变量标明`Bool`类型。初始化常量或者变量的时候如果所赋的值类型已知,就可以触发类型推导,这让 Swift 代码更加简洁并且可读性更高。
`orangesAreOrange`和`turnipsAreDelicious`的类型会被推测为`Bool`,因为它们的初值是布尔原始值。就像之前提到的`Int`和`Double`一样,如果你创建变量的时候给它们赋值`true`或者`false`,那你不需要给常量或者变量标明`Bool`类型。初始化常量或者变量的时候如果所赋的值类型已知,就可以触发类型推测,这让 Swift 代码更加简洁并且可读性更高。
当你编写条件语句比如`if`语句的时候,布尔值非常有用:
@ -417,7 +400,7 @@ Swift 有一个基本的布尔类型,叫做`Bool`。布尔值是指逻辑,
_Type casting_ is a way to check the type of an instance, and/or to treat that instance as if it is a different superclass or subclass from somewhere else in its own class hierarchy.
Type casting in Swift is implemented with the `is` and `as` operators. These two operators provide a simple and expressive way to check the type of a value or cast a value to a different type.
你也可以用来检查一个类是否实现了某个协议,就像在 [Protocols》Checking for Protocol Conformance](Protocols.html#//apple_ref/doc/uid/TP40014097-CH25-XID_363)部分讲述的一样。
You can also use type casting to check whether a type conforms to a protocol, as described in <spanclass="x-name">[Checking for Protocol Conformance](Protocols.html#//apple_ref/doc/uid/TP40014097-CH25-XID_363)</span>.
### 定义一个类层次作为例子Defining a Class Hierarchy for Type Casting
You can use type casting with a hierarchy of classes and subclasses to check the type of a particular class instance and to cast that instance to another class within the same hierarchy. The three code snippets below define a hierarchy of classes and an array containing instances of those classes, for use in an example of type casting.
The first snippet defines a new base class called `MediaItem`. This class provides basic functionality for any kind of item that appears in a digital media library. Specifically, it declares a `name` property of type `String`, and an `init name` initializer. (It is assumed that all media items, including all movies and songs, will have a name.)
The next snippet defines two subclasses of `MediaItem`. The first subclass, `Movie`, encapsulates additional information about a movie or film. It adds a `director` property on top of the base `MediaItem` class, with a corresponding initializer. The second subclass, `Song`, adds an `artist` property and initializer on top of the base class:
The final snippet creates a constant array called `library`, which contains two `Movie` instances and three `Song` instances. The type of the `library` array is inferred by initializing it with the contents of an array literal. Swift’s type checker is able to deduce that `Movie` and `Song` have a common superclass of `MediaItem`, and so it infers a type of `MediaItem[]` for the `library` array:
The items stored in `library` are still `Movie` and `Song` instances behind the scenes. However, if you iterate over the contents of this array, the items you receive back are typed as `MediaItem`, and not as `Movie` or `Song`. In order to work with them as their native type, you need to _check_ their type, or _downcast_ them to a different type, as described below.
Use the _type check operator_ (`is`) to check whether an instance is of a certain subclass type. The type check operator returns `true` if the instance is of that subclass type and `false` if it is not.
The example below defines two variables, `movieCount` and `songCount`, which count the number of `Movie` and `Song` instances in the `library` array:
var movieCount = 0
var songCount = 0
for item in library {
if item is Movie {
++movieCount
} else if item is Song {
++songCount
}
}
println("Media library contains \(movieCount) movies and \(songCount) songs")
// prints "Media library contains 2 movies and 3 songs"
示例迭代了数组 `library` 中的所有项。每一次, `for`-`in` 循环设置
`item` 常量的值为数组中的下一个 `MediaItem`。
This example iterates through all items in the `library` array. On each pass, the `for`-`in` loop sets the `item` constant to the next `MediaItem` in the array.
若当前 `MediaItem` 是一个 `Movie` 类型的实例, `item is Movie` 返回 `true`,相反返回 `false`。同样的,`item is Song`检查item是否为`Song`类型的实例。在循环末尾,`movieCount` 和 `songCount`的值就是被找到属于各自的类型的实例数量。
`item is Movie` returns `true` if the current `MediaItem` is a `Movie` instance and `false` if it is not. Similarly, `item is Song` checks whether the item is a `Song` instance. At the end of the `for`-`in` loop, the values of `movieCount` and `songCount` contain a count of how many `MediaItem` instances were found of each type.
A constant or variable of a certain class type may actually refer to an instance of a subclass behind the scenes. Where you believe this is the case, you can try to _downcast_ to the subclass type with the _type cast operator_ (`as`).
Because downcasting can fail, the type cast operator comes in two different forms. The optional form, `as?`, returns an optional value of the type you are trying to downcast to. The forced form, `as`, attempts the downcast and force-unwraps the result as a single compound action.
Use the optional form of the type cast operator (`as?`) when you are not sure if the downcast will succeed. This form of the operator will always return an optional value, and the value will be `nil` if the downcast was not possible. This enables you to check for a successful downcast.
Use the forced form of the type cast operator (`as`) only when you are sure that the downcast will always succeed. This form of the operator will trigger a runtime error if you try to downcast to an incorrect class type.
The example below iterates over each `MediaItem` in `library`, and prints an appropriate description for each item. To do this, it needs to access each item as a true `Movie` or `Song`, and not just as a `MediaItem`. This is necessary in order for it to be able to access the `director` or `artist` property of a `Movie` or `Song` for use in the description.
In this example, each item in the array might be a `Movie`, or it might be a `Song`. You don’t know in advance which actual class to use for each item, and so it is appropriate to use the optional form of the type cast operator (`as?`) to check the downcast each time through the loop:
for item in library {
if let movie = item as? Movie {
println("Movie: '\(movie.name)', dir. \(movie.director)")
} else if let song = item as? Song {
println("Song: '\(song.name)', by \(song.artist)")
}
}
// Movie: 'Casablanca', dir. Michael Curtiz
// Song: 'Blue Suede Shoes', by Elvis Presley
// Movie: 'Citizen Kane', dir. Orson Welles
// Song: 'The One And Only', by Chesney Hawkes
// Song: 'Never Gonna Give You Up', by Rick Astley
The example starts by trying to downcast the current `item` as a `Movie`. Because `item` is a `MediaItem` instance, it’s possible that it _might_ be a `Movie`; equally, it’s also possible that it might a `Song`, or even just a base `MediaItem`. Because of this uncertainty, the `as?` form of the type cast operator returns an _optional_ value when attempting to downcast to a subclass type. The result of `item as Movie` is of type `Movie?`, or “optional `Movie`”.
当应用在两个`Song`实例时,下转为 `Movie` 失败。为了处理这种情况,上面的实例使用了可选绑定(optional binding)来检查optional `Movie`真的包含一个值(这个是为了判断下转是否成功。)可选绑定是这样写的“`if let movie = item as? Movie`”,可以这样解读:
Downcasting to `Movie` fails when applied to the two `Song` instances in the library array. To cope with this, the example above uses optional binding to check whether the optional `Movie` actually contains a value (that is, to find out whether the downcast succeeded.) This optional binding is written “`if let movie = item as? Movie`”, which can be read as:
“Try to access `item` as a `Movie`. If this is successful, set a new temporary constant called `movie` to the value stored in the returned optional `Movie`.”
If the downcasting succeeds, the properties of `movie` are then used to print a description for that `Movie` instance, including the name of its `director`. A similar principle is used to check for `Song` instances, and to print an appropriate description (including `artist` name) whenever a `Song` is found in the library.
注意
转换没有真的改变实例或它的值。潜在的根本的实例保持不变;只是简单地把它作为它被转换成的类来使用。
NOTE
Casting does not actually modify the instance or change its values. The underlying instance remains the same; it is simply treated and accessed as an instance of the type to which it has been cast.
### Any和AnyObject的转换 Type Casting for Any and AnyObject
Swift为不确定类型提供了两种特殊类型别名:
*`AnyObject`可以代表任何class类型的实例。
*`Any`可以表示任何类型,除了方法类型(function types)。
Swift provides two special type aliases for working with non-specific types:
*`AnyObject` can represent an instance of any class type.
*`Any` can represent an instance of any type at all, apart from function types.
Use Any and AnyObject only when you explicitly need the behavior and capabilities they provide. It is always better to be specific about the types you expect to work with in your code.
When working with Cocoa APIs, it is common to receive an array with a type of `AnyObject[]`, or “an array of values of any object type”. This is because Objective-C does not have explicitly typed arrays. However, you can often be confident about the type of objects contained in such an array just from the information you know about the API that provided the array.
In these situations, you can use the forced version of the type cast operator (`as`) to downcast each item in the array to a more specific class type than `AnyObject`, without the need for optional unwrapping.
下面的示例定义了一个 `AnyObject[]` 类型的数组并填入三个`Movie`类型的实例:
The example below defines an array of type `AnyObject[]` and populates this array with three instances of the `Movie` class:
let someObjects: AnyObject[] = [
Movie(name: "2001: A Space Odyssey", director: "Stanley Kubrick"),
Because this array is known to contain only `Movie` instances, you can downcast and unwrap directly to a non-optional `Movie` with the forced version of the type cast operator (`as`):
for object in someObjects {
let movie = object as Movie
println("Movie: '\(movie.name)', dir. \(movie.director)")
}
// Movie: '2001: A Space Odyssey', dir. Stanley Kubrick
Here’s an example of using `Any` to work with a mix of different types, including non-class types. The example creates an array called `things`, which can store values of type `Any`:
The `things` array contains two `Int` values, two `Double` values, a `String` value, a tuple of type `(Double, Double)`, and the movie “Ghostbusters”, directed by Ivan Reitman.
You can use the `is` and `as` operators in a `switch` statement’s cases to discover the specific type of a constant or variable that is known only to be of type `Any` or `AnyObject`. The example below iterates over the items in the `things` array and queries the type of each item with a `switch` statement. Several of the `switch` statement’s cases bind their matched value to a constant of the specified type to enable its value to be printed:
for thing in things {
switch thing {
case 0 as Int:
println("zero as an Int")
case 0 as Double:
println("zero as a Double")
case let someInt as Int:
println("an integer value of \(someInt)")
case let someDouble as Double where someDouble > 0:
println("a positive double value of \(someDouble)")
case is Double:
println("some other double value that I don't want to print")
case let someString as String:
println("a string value of \"\(someString)\"")
case let (x, y) as (Double, Double):
println("an (x, y) point at \(x), \(y)")
case let movie as Movie:
println("a movie called '\(movie.name)', dir. \(movie.director)")
default:
println("something else")
}
}
// zero as an Int
// zero as a Double
// an integer value of 42
// a positive double value of 3.14159
// a string value of "hello"
// an (x, y) point at 3.0, 5.0
// a movie called 'Ghostbusters', dir. Ivan Reitman
。
注意
在一个switch语句的case中使用强制形式的类型检查操作符(as, 而不是 as?) 来检查和转换到一个规定的类型。在switch case 语句的内容中这种检查总是安全的。
NOTE
The cases of a switch statement use the forced version of the type cast operator (as, not as?) to check and cast to a specific type. This check is always safe within the context of a switch case statement.
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.