未翻译完 待续(英语烂,求斧正)

Type Casting

类型转换

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.

在swift中类型转换是is和as运算符的实现。这两个算符提供了一个简单的和有表现力的方式来检测一个值的类型或把一个值转换为不同的类型。

You can also use type casting to check whether a type conforms to a protocol, as described in Checking for Protocol Conformance.

你还可以使用类型转换来检查一个类型是否符合某个协议,如检查协议的一致性描述。

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.)

第一个片段定义了一个名为MediaItem新的基类。这个类为出现在数字媒体库中任何类型的项目提供基本的功能。具体来说,它声明一个String类型的name属性,以及一个init name初始化构造器。 (假设所有的媒体项目,包括所有的电影和歌曲,将有一个名称。)

    class MediaItem {
var name: String
init(name: String) {
self.name = 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:

接下来的片断定义MediaItem的两个子类。第一个子类,Movie,封装了有关电影或影片的附加信息。它伴随着相应的初始化构造器,在基类MediaItem的顶部增加了一个director属性,。第二个子类Song在基类的顶部增加了一个artist属性和初始化构造器:

    class Movie: MediaItem {
var director: String
init(name: String, director: String) {
self.director = director
super.init(name: name)
}
}
class Song: MediaItem {
var artist: String
init(name: String, artist: String) {
self.artist = artist
super.init(name: name)
}
}

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:

  • let library = [
  • Movie(name: "Casablanca", director: "Michael Curtiz"),
  • Song(name: "Blue Suede Shoes", artist: "Elvis Presley"),
  • Movie(name: "Citizen Kane", director: "Orson Welles"),
  • Song(name: "The One And Only", artist: "Chesney Hawkes"),
  • Song(name: "Never Gonna Give You Up", artist: "Rick Astley")
  • ]
  • // the type of "library" is inferred to be MediaItem[]

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.

Checking Type

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"

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.

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.

Downcasting

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”.

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.

Type Casting for Any and AnyObject

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.

Note

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.

AnyObject

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.

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"),
  • Movie(name: "Moon", director: "Duncan Jones"),
  • Movie(name: "Alien", director: "Ridley Scott")
  • ]

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
  • // Movie: 'Moon', dir. Duncan Jones
  • // Movie: 'Alien', dir. Ridley Scott

For an even shorter form of this loop, downcast the someObjects array to a type of Movie[] instead of downcasting each item:

  • for movie in someObjects as Movie[] {
  • println("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

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:

  • var things = Any[]()
  • things.append(0)
  • things.append(0.0)
  • things.append(42)
  • things.append(3.14159)
  • things.append("hello")
  • things.append((3.0, 5.0))
  • things.append(Movie(name: "Ghostbusters", director: "Ivan Reitman"))

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

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.

swift中文文档- 类型转换的更多相关文章

  1. Swift语言教程中文文档

    Swift语言教程中文文档 Swift语言教程(一)基础数据类型 Swift语言教程(二)基础数据类型 Swift语言教程(三)集合类型 Swift语言教程(四) 集合类型 Swift语言教程(五)控 ...

  2. Spring中文文档

    前一段时间翻译了Jetty的一部分文档,感觉对阅读英文没有大的提高(*^-^*),毕竟Jetty的受众面还是比较小的,而且翻译过程中发现Jetty的文档写的不是很好,所以呢翻译的兴趣慢慢就不大了,只能 ...

  3. Sails.js中文文档

    Sails.js中文文档   http://sailsdoc.swift.ren/ Sails.js是一个Web框架,可以于轻松构建自定义,企业级Node.js Apps.它在设计上类似于像Ruby ...

  4. PyTorch官方中文文档:torch.nn

    torch.nn Parameters class torch.nn.Parameter() 艾伯特(http://www.aibbt.com/)国内第一家人工智能门户,微信公众号:aibbtcom ...

  5. Apache Spark 2.2.0 中文文档

    Apache Spark 2.2.0 中文文档 - 快速入门 | ApacheCN Geekhoo 关注 2017.09.20 13:55* 字数 2062 阅读 13评论 0喜欢 1 快速入门 使用 ...

  6. Solidity 最新 0.5.8 中文文档发布

    本文首发于深入浅出区块链社区 热烈祝贺 Solidity 最新 0.5.8 中文文档发布, 这不单是一份 Solidity 速查手册,更是一份深入以太坊智能合约开发宝典. 翻译说明 Solidity ...

  7. Kotlin 中文文档

    Kotlin 中文文档 标签: Kotlinkotlin中文文档 2017-02-14 18:14 4673人阅读 评论(0) 收藏 举报  分类: kotlin 转载地址:http://www.tu ...

  8. Sails.js中文文档,Sails中文文档

    Sails.js中文文档   http://sailsdoc.swift.ren/ Sails.js是一个Web框架,可以于轻松构建自定义,企业级Node.js Apps.它在设计上类似于像Ruby ...

  9. Mockito 中文文档 ( 2.0.26 beta )

    Mockito 中文文档 ( 2.0.26 beta ) 由于缺乏校对,难免有谬误之处,如果发现任何语句不通顺.翻译错误,都可以在github中的项目提出issue.谢谢~ Mockito框架官方地址 ...

随机推荐

  1. Sublime Text 2 - 性感无比的代码编辑器!程序员必备神器!跨平台支持Win/Mac/Linux

    我用过的编辑器不少,真不少- 但却没有哪款让我特别心仪的,直到我遇到了 Sublime Text 2 !如果说“神器”是我能给予一款软件最高的评价,那么我很乐意为它封上这么一个称号.它小巧绿色且速度非 ...

  2. Chrome调试工具简单介绍

    作为前端开发者都知道,快捷键F12可以打开chrome调试工具.firefox可以打开firebug工具.“工欲善其事,必先利其器”,对调试工具的掌握,能大大提高我们调试代码的效率.因为我平常chro ...

  3. IOS开发之——类似微信摇一摇的功能实现

    首先,一直以为摇一摇的功能实现好高大上,结果百度了.我自己也模仿写了一个demo.主要代码如下: 新建一个项目,名字为AnimationShake. 主要代码: - (void)motionBegan ...

  4. UIPasteboard的使用

    剪贴板的使用以及自定义剪贴板. 系统剪贴板的直接调用 其实整个过程非常的简单,我就用我写的一个自定义UILable来说明调用系统剪贴板. 首先,因为苹果只放出来了 UITextView,UITextF ...

  5. BASE64Decoder 编码(sun.jar)

    Base64 是网络上最常见的用于传输8Bit 字节代码的编码方式之一,大家可以查看RFC2045 -RFC2049 ,上面有MIME 的详细规范.  Base64 要求把每三个8Bit 的字节转换为

  6. IDL简介与corba入门案例

    IDL接口定义语言简介   IDL用中立语言的方式进行描述,能使软件组建(不同语言编写的)间相互通信. IDL提供了一个桥来连接不同的系统. Corba 上的服务用IDL描述,将被映射为某种程序设计语 ...

  7. [USACO2002][poj1944]Fiber Communications(枚举)

    Fiber Communications Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 3804   Accepted: 1 ...

  8. base-css

    html{ min-width: 320px;}body{ min-width: 320px; overflow-x:hidden }@media print { * { background: tr ...

  9. CAS做单点登陆(SSO)——集成BIEE 11g

    BIEE 11G和CAS集成零代码编写,只需配置. 更改BIEE analytics应用的web.xml 将analytics.war解包(使用7-zip或者Win-rar就可以),然后修改WEB-I ...

  10. opencv笔记5:频域和空域的一点理解

    time:2015年10月06日 星期二 12时14分51秒 # opencv笔记5:频域和空域的一点理解 空间域和频率域 傅立叶变换是f(t)乘以正弦项的展开,正弦项的频率由u(其实是miu)的值决 ...