Swift-類型轉(zhuǎn)換

  • 類型轉(zhuǎn)換可以判斷實(shí)例的類型昭抒,也可以將實(shí)例看做是其父類或者子類的實(shí)例蚀浆。
  • 類型轉(zhuǎn)換在 Swift 中使用 is 和 as 操作符實(shí)現(xiàn)。
  • 也可以用它來檢查一個(gè)類型是否遵循了某個(gè)協(xié)議。

1. 為類型轉(zhuǎn)換定義類層次

  • 可以將類型轉(zhuǎn)換用在類和子類的層次結(jié)構(gòu)上钻哩,檢查特定類實(shí)例的類型并且轉(zhuǎn)換這個(gè)類實(shí)例的類型成為這個(gè)層次結(jié)構(gòu)中的其他類型。
/*
這個(gè)類為任何出現(xiàn)在數(shù)字媒體庫的媒體項(xiàng)提供基礎(chǔ)功能肛冶。
特別的街氢,它聲明了一個(gè) String 類型的 name 屬性,和一個(gè) init(name:) 初始化器睦袖。
*/
class MediaItem {
    var name: String
    init(name: String) {
        self.name = name
    }
}

/*
子類 Movie 封裝了與電影相關(guān)的額外信息
在父類(或者說基類)的基礎(chǔ)上增加了一個(gè) director(導(dǎo)演)屬性珊肃,和相應(yīng)的初始化器。
*/
class Movie: MediaItem {
    var director: String
    init(name: String, director: String) {
        self.director = director
        super.init(name: name)
    }
}
/*
子類 Song馅笙,在父類的基礎(chǔ)上增加了一個(gè) artist(藝術(shù)家)屬性伦乔,和相應(yīng)的初始化器
*/
class Song: MediaItem {
    var artist: String
    init(name: String, artist: String) {
        self.artist = artist
        super.init(name: name)
    }
}

/*
創(chuàng)建了一個(gè)數(shù)組常量 library,包含兩個(gè) Movie 實(shí)例和三個(gè) Song 實(shí)例董习。
library 的類型是在它被初始化時(shí)根據(jù)它數(shù)組中所包含的內(nèi)容推斷來的烈和。
Swift 的類型檢測(cè)器能夠推斷出 Movie 和 Song 有共同的父類 MediaItem,所以它推斷出 [MediaItem] 類作為 library 的類型
*/
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")
]   // 數(shù)組 library 的類型被推斷為 [MediaItem]

library 里存儲(chǔ)的媒體項(xiàng)依然是 Movie 和 Song 類型的阱飘。
但是斥杜,若你迭代它,依次取出的實(shí)例會(huì)是 MediaItem 類型的沥匈,而不是 Movie 和 Song 類型蔗喂。
為了讓它們作為原本的類型工作,你需要檢查它們的類型或者向下轉(zhuǎn)換它們到其它類型高帖。

2. 檢查類型

  • 用類型檢查操作符(is)來檢查一個(gè)實(shí)例是否屬于特定子類型缰儿。
  • 若實(shí)例屬于那個(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") // 打印“Media library contains 2 movies and 3 songs”

迭代了數(shù)組 library 中的所有項(xiàng)宣赔。
每一次,for-in 循環(huán)設(shè)置 item 常量為數(shù)組中的下一個(gè) MediaItem 實(shí)例瞪浸。
若當(dāng)前 MediaItem 是一個(gè) Movie 類型的實(shí)例儒将,item is Movie 返回 true,否則返回 false对蒲。
同樣的钩蚊,item is Song 檢查 item 是否為 Song 類型的實(shí)例。
在循環(huán)結(jié)束后蹈矮,movieCount 和 songCount 的值就是被找到的屬于各自類型的實(shí)例的數(shù)量砰逻。

3. 向下轉(zhuǎn)型

  • 某類型的一個(gè)常量或變量可能在幕后實(shí)際上屬于一個(gè)子類。
  • 當(dāng)確定是這種情況時(shí)泛鸟,你可以嘗試用類型轉(zhuǎn)換操作符(as? 或 as!)向下轉(zhuǎn)到它的子類型蝠咆。
  • 因?yàn)橄蛳罗D(zhuǎn)型可能會(huì)失敗,類型轉(zhuǎn)型操作符帶有兩種不同形式北滥。
    • 條件形式 as? 返回一個(gè)你試圖向下轉(zhuǎn)成的類型的可選值刚操。
      • 當(dāng)你不確定向下轉(zhuǎn)型可以成功時(shí),用類型轉(zhuǎn)換的條件形式(as?)再芋。條件形式的類型轉(zhuǎn)換總是返回一個(gè)可選值赡茸,并且若下轉(zhuǎn)是不可能的,可選值將是 nil祝闻。這使你能夠檢查向下轉(zhuǎn)型是否成功。
    • 強(qiáng)制形式 as! 把試圖向下轉(zhuǎn)型和強(qiáng)制解包轉(zhuǎn)換結(jié)果結(jié)合為一個(gè)操作遗菠。
      • 只有你可以確定向下轉(zhuǎn)型一定會(huì)成功時(shí)联喘,才使用強(qiáng)制形式(as!)。當(dāng)你試圖向下轉(zhuǎn)型為一個(gè)不正確的類型時(shí)辙纬,強(qiáng)制形式的類型轉(zhuǎn)換會(huì)觸發(fā)一個(gè)運(yùn)行時(shí)錯(cuò)誤豁遭。
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)")
    }
}

// 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 轉(zhuǎn)為 Movie 類型。若成功贺拣,設(shè)置一個(gè)新的臨時(shí)常量 movie 來存儲(chǔ)返回的可選 Movie 中的值蓖谢。
若向下轉(zhuǎn)型成功,然后 movie 的屬性將用于打印一個(gè) Movie 實(shí)例的描述譬涡,包括它的導(dǎo)演的名字 director闪幽。
相似的原理被用來檢測(cè) Song 實(shí)例,當(dāng) Song 被找到時(shí)則打印它的描述(包含 artist 的名字)涡匀。

注意:轉(zhuǎn)換沒有真的改變實(shí)例或它的值盯腌。根本的實(shí)例保持不變;只是簡單地把它作為它被轉(zhuǎn)換成的類型來使用陨瘩。

4. Any 和 AnyObject 的類型轉(zhuǎn)換

Swift 為不確定類型提供了兩種特殊的類型別名:

  • Any 可以表示任何類型腕够,包括函數(shù)類型级乍。
  • AnyObject 可以表示任何類類型的實(shí)例。

只有當(dāng)你確實(shí)需要它們的行為和功能時(shí)才使用 Any 和 AnyObject帚湘。最好還是在代碼中指明需要使用的類型玫荣。

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)" })
  • 可以在 switch 表達(dá)式的 case 中使用 is 和 as 操作符來找出只知道是 Any 或 AnyObject 類型的常量或變量的具體類型。
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 類型可以表示所有類型的值大诸,包括可選類型捅厂。
  • Swift 會(huì)在你用 Any 類型來表示一個(gè)可選值的時(shí)候,給你一個(gè)警告底挫。
  • 如果你確實(shí)想使用 Any 類型來承載可選值恒傻,你可以使用 as 操作符顯式轉(zhuǎn)換為 Any。
let optionalNumber: Int? = 3
things.append(optionalNumber)        // 警告
things.append(optionalNumber as Any) // 沒有警告
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末建邓,一起剝皮案震驚了整個(gè)濱河市盈厘,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌官边,老刑警劉巖沸手,帶你破解...
    沈念sama閱讀 218,941評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異注簿,居然都是意外死亡契吉,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門诡渴,熙熙樓的掌柜王于貴愁眉苦臉地迎上來捐晶,“玉大人,你說我怎么就攤上這事妄辩』罅椋” “怎么了?”我有些...
    開封第一講書人閱讀 165,345評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵眼耀,是天一觀的道長英支。 經(jīng)常有香客問我,道長哮伟,這世上最難降的妖魔是什么干花? 我笑而不...
    開封第一講書人閱讀 58,851評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮楞黄,結(jié)果婚禮上池凄,老公的妹妹穿的比我還像新娘。我一直安慰自己谅辣,他們只是感情好修赞,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,868評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般柏副。 火紅的嫁衣襯著肌膚如雪勾邦。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,688評(píng)論 1 305
  • 那天割择,我揣著相機(jī)與錄音眷篇,去河邊找鬼。 笑死荔泳,一個(gè)胖子當(dāng)著我的面吹牛蕉饼,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播玛歌,決...
    沈念sama閱讀 40,414評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼昧港,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼!你這毒婦竟也來了支子?” 一聲冷哼從身側(cè)響起创肥,我...
    開封第一講書人閱讀 39,319評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎值朋,沒想到半個(gè)月后叹侄,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,775評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡昨登,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評(píng)論 3 336
  • 正文 我和宋清朗相戀三年趾代,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片丰辣。...
    茶點(diǎn)故事閱讀 40,096評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡撒强,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出笙什,到底是詐尸還是另有隱情尿褪,我是刑警寧澤,帶...
    沈念sama閱讀 35,789評(píng)論 5 346
  • 正文 年R本政府宣布得湘,位于F島的核電站,受9級(jí)特大地震影響顿仇,放射性物質(zhì)發(fā)生泄漏淘正。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,437評(píng)論 3 331
  • 文/蒙蒙 一臼闻、第九天 我趴在偏房一處隱蔽的房頂上張望鸿吆。 院中可真熱鬧,春花似錦述呐、人聲如沸惩淳。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽思犁。三九已至代虾,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間激蹲,已是汗流浹背棉磨。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評(píng)論 1 271
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留学辱,地道東北人乘瓤。 一個(gè)月前我還...
    沈念sama閱讀 48,308評(píng)論 3 372
  • 正文 我出身青樓,卻偏偏與公主長得像策泣,于是被迫代替她去往敵國和親衙傀。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,037評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 類型轉(zhuǎn)換是一種檢查實(shí)例類型的方法,或者將該實(shí)例視為來自其自身類層次結(jié)構(gòu)中的其他地方的不同超類或子類任洞。Swift中的...
    Joker_King閱讀 2,522評(píng)論 0 0
  • 類型轉(zhuǎn)換 可以判斷實(shí)例的類型蓄喇,也可以將實(shí)例看做是其父類或者子類的實(shí)例。 類型轉(zhuǎn)換在 Swift 中使用 is 和 ...
    CDLOG閱讀 4,803評(píng)論 0 1
  • 中文文檔 類型轉(zhuǎn)換可以判斷實(shí)例的類型交掏,也可以將實(shí)例看做是其父類或者子類的實(shí)例妆偏。 一、定義一個(gè)類層次作為例子 你可以...
    伯wen閱讀 205評(píng)論 0 0
  • Swift 語言類型轉(zhuǎn)換可以判斷實(shí)例的類型盅弛。也可以用于檢測(cè)實(shí)例類型是否屬于其父類或者子類的實(shí)例钱骂。 Swift 中類...
    零度_不結(jié)冰閱讀 285評(píng)論 0 0
  • 前言:本篇文章的目的,在于記錄學(xué)習(xí)過程,敦促自己挪鹏,方便查看见秽。練習(xí)工具:Playground學(xué)習(xí)網(wǎng)站: swift5...
    麥穗0615閱讀 343評(píng)論 0 0