【Swift 3.1】19 - 類型轉(zhuǎn)換 (Type Casting)
自從蘋(píng)果2014年發(fā)布Swift镜会,到現(xiàn)在已經(jīng)兩年多了,而Swift也來(lái)到了3.1版本阳柔。去年利用工作之余佳吞,共花了兩個(gè)多月的時(shí)間把官方的Swift編程指南看完⊥妫現(xiàn)在整理一下筆記,回顧一下以前的知識(shí)苏章。有需要的同學(xué)可以去看官方文檔>>寂嘉。
類型轉(zhuǎn)換是用來(lái)檢查實(shí)例的類型,或在繼承鏈中把實(shí)例作為不同的父類或子類的一種方法枫绅。
Swift中的類型轉(zhuǎn)換用is
和as
來(lái)實(shí)現(xiàn)泉孩。
為類型轉(zhuǎn)換定義一個(gè)類的層次結(jié)構(gòu) (Defining a Class Hierarchy for Type Casting)
第一個(gè)類是MediaItem
。假設(shè)所有的媒體項(xiàng)目并淋,包括電影和音樂(lè)寓搬,并且有名字:
class MediaItem {
var name: String
init(name: String) {
self.name = name
}
}
第二個(gè)類是MediaItem
的子類Movie
。第三個(gè)也是MediaItem
的子類:
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)
}
}
最后創(chuàng)建了一個(gè)library
數(shù)組县耽,包含了兩個(gè)Movie
實(shí)例和三個(gè)Song
實(shí)例句喷。Swift根據(jù)字面值推斷出library
是[MediaItem]
類型:
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]
雖然這個(gè)數(shù)組裝的是Movie
和Song
實(shí)例,但如果遍歷這個(gè)數(shù)組兔毙,取出來(lái)的元素是MediaItem
類型唾琼,而不是Movie
和Song
類型。為了使用他們的真實(shí)類型澎剥,我們需要檢查他們的類型锡溯,或者向下轉(zhuǎn)型。
檢查類型 (Checking Type)
使用is
來(lái)檢查一個(gè)實(shí)例是否是一個(gè)子類類型肴裙。如果是一個(gè)子類類型趾唱,返回true
,否則返回false
蜻懦。
var movieCount = 0
var songCount = 0
for item in library {
if item is Movie {
movieCount += 1
}
else if item is Song {
songCount += 1
}
}
print("Media library contains \(movieCount) movies and \(songCount) songs")
// Prints "Media library contains 2 movies and 3 songs"
向下轉(zhuǎn)型 (Downcasting)
一個(gè)類型的常量或變量實(shí)際上可能是子類的實(shí)例類型甜癞,我們可以使用as?
或者as!
來(lái)向下轉(zhuǎn)型到子類類型。
因?yàn)橄蛳罗D(zhuǎn)型可能會(huì)失敗宛乃,所以轉(zhuǎn)型運(yùn)算符有兩種類型悠咱。as?
返回你想轉(zhuǎn)到的那個(gè)類型的可選類型;而as!
如果轉(zhuǎn)型成功征炼,返回你想轉(zhuǎn)到的那個(gè)類型析既,轉(zhuǎn)型失敗將會(huì)報(bào)錯(cuò)。
如果不確定是否能轉(zhuǎn)型成功谆奥,使用as?
眼坏;如果能確定轉(zhuǎn)型成功,使用as!
酸些。
for item in library {
if let movie = item as? Movie {
print("Movie: \(movie.name), dir. \(movie.director)")
}
else if let song = item as? Song {
print("Song: \(song.name), by \(song.artist)")
}
}
注意:轉(zhuǎn)型實(shí)際上不會(huì)修改實(shí)例或者改變它的值宰译,在底層中檐蚜,還是同一個(gè)實(shí)例。
Any和AnyObject的類型轉(zhuǎn)換 (Type Casting for Any and AnyObject)
Swift提供了兩種不確定的類型:
-
Any
可以代表任何類型的實(shí)例沿侈,包括方法類型 -
AnyObject
代表任何class類型的實(shí)例
下面是一個(gè)例子:
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"))
things.append({ (name: String) -> String in "Hello, \(name)" })
向下轉(zhuǎn)型:
for thing in things {
switch thing {
case 0 as Int:
print("zero as an Int")
case 0 as Double:
print("zero as a Double")
case let someInt as Int:
print("an integer value of \(someInt)")
case let someDouble as Double where someDouble > 0:
print("a positive double value of \(someDouble)")
case is Double:
print("some other double value that I don't want to print")
case let someString as String:
print("a string value of \"\(someString)\"")
case let (x, y) as (Double, Double):
print("an (x, y) point at \(x), \(y)")
case let movie as Movie:
print("a movie called \(movie.name), dir. \(movie.director)")
case let stringConverter as (String) -> String:
print(stringConverter("Michael"))
default:
print("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
// Hello, Michael
注意: Any
代表任何類型的值闯第,包括可選類型。如果在需要傳入Any
類型的位置傳入一個(gè)可選類型的值缀拭,Swift會(huì)給你一個(gè)警告咳短。如果確實(shí)需要把可選類型的值作為一個(gè)Any
類型的值,可以使用as
來(lái)明確地轉(zhuǎn)為Any
類型:
let optionalNumber: Int? = 3
things.append(optionalNumber) // Warning
things.append(optionalNumber as Any) // No warning
第十九部分完蛛淋。下個(gè)部分:【Swift 3.1】20 - 嵌套類型 (Nested Types)
如果有錯(cuò)誤的地方咙好,歡迎指正!謝謝褐荷!