类型转换 可以判断实例的类型,也可以将实例看做是其父类或者子类的实例。
类型转换在 Swift 中使用 is
和 as
操作符实现。这两个操作符提供了一种简单达意的方式去检查值的类型或者转换它的类型。
定义一个类层次作为例子
你可以将类型转换用在类和子类的层次结构上,检查特定类实例的类型并且转换这个类实例的类型成为这个层次结构中的其他类型。
class MediaItem {
var name: String
init(name: String) {
self.name = name
}
}
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)
}
}
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")
]
// 数组 library 的类型被推断为 [MediaItem]
检查类型(Checking Type)
用类型检查操作符(is
)来检查一个实例是否属于特定子类型。若实例属于那个子类型,类型检查操作符返回 true
,否则返回 false
。
var movieCount = 0
var songCount = 0
for item in library {
if item is Movie {
++movieCount
} else if item is Song {
++songCount
}
}
print("Media library contains \(movieCount) movies and \(songCount) songs")
// 打印 “Media library contains 2 movies and 3 songs”
向下转型(Downcasting)
某类型的一个常量或变量可能在幕后实际上属于一个子类。当确定是这种情况时,你可以尝试向下转到它的子类型,用类型转换操作符(as?
或 as!
)。
因为向下转型可能会失败,类型转型操作符带有两种不同形式。条件形式(conditional form)as?
返回一个你试图向下转成的类型的可选值(optional value)。强制形式 as!
把试图向下转型和强制解包(force-unwraps)转换结果结合为一个操作。
当你不确定向下转型可以成功时,用类型转换的条件形式(as?
)。条件形式的类型转换总是返回一个可选值(optional value),并且若下转是不可能的,可选值将是 nil
。这使你能够检查向下转型是否成功。
只有你可以确定向下转型一定会成功时,才使用强制形式(as!
)。当你试图向下转型为一个不正确的类型时,强制形式的类型转换会触发一个运行时错误。
ps: 转换没有真的改变实例或它的值。根本的实例保持不变;只是简单地把它作为它被转换成的类型来使用。
Any
和 AnyObject
的类型转换
Swift 为不确定类型提供了两种特殊的类型别名:
-
AnyObject
可以表示任何类类型的实例。 -
Any
可以表示任何类型,包括函数类型。
ps: 只有当你确实需要它们的行为和功能时才使用
Any
和AnyObject
。在你的代码里使用你期望的明确类型总是更好的。
要点总结
Any
是表示任何类型。当然也包括类类型。也就是说AnyObject
是Any
的子集喽。