发布于 2015-06-14 01:45:39 | 310 次阅读 | 评论: 0 | 来源: 网络整理

向下转型(Downcasting)

某类型的一个常量或变量可能在幕后实际上属于一个子类。你可以相信,上面就是这种情况。你可以尝试向下转到它的子类型,用类型转换操作符(as)

因为向下转型可能会失败,类型转型操作符带有两种不同形式。可选形式( optional form) as? 返回一个你试图下转成的类型的可选值(optional value)。强制形式 as 把试图向下转型和强制解包(force-unwraps)结果作为一个混合动作。

当你不确定向下转型可以成功时,用类型转换的可选形式(as?)。可选形式的类型转换总是返回一个可选值(optional value),并且若下转是不可能的,可选值将是 nil 。这使你能够检查向下转型是否成功。

只有你可以确定向下转型一定会成功时,才使用强制形式。当你试图向下转型为一个不正确的类型时,强制形式的类型转换会触发一个运行时错误。

下面的例子,迭代了library里的每一个 MediaItem ,并打印出适当的描述。要这样做,item需要真正作为Movie 或 Song的类型来使用。不仅仅是作为 MediaItem。为了能够使用Movie 或 Songdirector 或 artist属性,这是必要的。

在这个示例中,数组中的每一个item可能是 Movie 或 Song。 事前你不知道每个item的真实类型,所以这里使用可选形式的类型转换 (as?)去检查循环里的每次下转。


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

示例首先试图将 item 下转为 Movie。因为 item 是一个 MediaItem 类型的实例,它可能是一个Movie;同样,它可能是一个 Song,或者仅仅是基类 MediaItem。因为不确定,as?形式在试图下转时将返还一个可选值。 item as Movie 的返回值是Movie?类型或 “optional Movie”。

当向下转型为 Movie 应用在两个 Song 实例时将会失败。为了处理这种情况,上面的例子使用了可选绑定(optional binding)来检查可选 Movie真的包含一个值(这个是为了判断下转是否成功。)可选绑定是这样写的“if let movie = item as? Movie”,可以这样解读:

“尝试将 item 转为 Movie类型。若成功,设置一个新的临时常量 movie 来存储返回的可选Movie

若向下转型成功,然后movie的属性将用于打印一个Movie实例的描述,包括它的导演的名字director。当Song被找到时,一个相近的原理被用来检测 Song 实例和打印它的描述。


注意:
转换没有真的改变实例或它的值。潜在的根本的实例保持不变;只是简单地把它作为它被转换成的类来使用。
 

最新网友评论  共有(0)条评论 发布评论 返回顶部

Copyright © 2007-2017 PHPERZ.COM All Rights Reserved   冀ICP备14009818号  版权声明  广告服务