
1.類型檢查符is
類型檢查操作符is,可以檢查一個(gè)對(duì)象是不是某個(gè)類的對(duì)象,如果是,則返回true,否則返回false
class Person{
var name:String?
init(name:String) {
self.name = name;
}
}
class Employee: Person {
var company:String
init(name:String,company:String) {
self.company = company
super.init(name: name)
}
}
class Student: Person {
var school:String?
init(name:String,school:String) {
self.school = school
super.init(name: name)
}
}
let employee1 = Employee(name:"張三",company:"apple公司")
let employee2 = Employee(name:"李四",company:"google公司")
let student1 = Student(name:"小明",school:"中關(guān)村一小")
let student2 = Student(name:"小花",school:"中關(guān)村二小")
let student3 = Student(name:"小路",school:"中關(guān)村二小")
let members = [employee1,employee2,student1,student2,student3];
var employeeCount = 0
var studentCount = 0
for item in members{
if item is Employee{
employeeCount += 1;
}else if item is Student{
studentCount += 1;
}
}
print("職員的人數(shù):\(employeeCount)人") // 打印 職員的人數(shù):2人
print("學(xué)生的人數(shù):\(studentCount)人") // 打印 學(xué)生的人數(shù):3人
2.類型轉(zhuǎn)換as操作符
類型轉(zhuǎn)換時(shí)將一個(gè)類型轉(zhuǎn)換為另外一個(gè)類型,但是前提是有繼承關(guān)系的,對(duì)象的類型之間才可以轉(zhuǎn)換,將子類轉(zhuǎn)換成父類,是向上轉(zhuǎn)換,一般都會(huì)轉(zhuǎn)換成功,將父類轉(zhuǎn)換成子類是向下轉(zhuǎn)換,可能會(huì)失敗
類型轉(zhuǎn)換的操作符有兩種形式:as?和as!,條件形式as?返回目標(biāo)類型的可選值,強(qiáng)制形式as!把向下轉(zhuǎn)型和強(qiáng)制解包轉(zhuǎn)型結(jié)果結(jié)合為一個(gè)操作
as!操作符是類型轉(zhuǎn)換的強(qiáng)制格式,如果可以轉(zhuǎn)換,則會(huì)返回轉(zhuǎn)換了格式的對(duì)象,如果無法轉(zhuǎn)換就會(huì)拋出運(yùn)行時(shí)錯(cuò)誤。因此除非百分之百確定可以轉(zhuǎn)換,否則不應(yīng)該使用as!來進(jìn)行強(qiáng)制類型轉(zhuǎn)換。
和is操作符非常類似,類型轉(zhuǎn)換的規(guī)則是,某個(gè)類的對(duì)象可以轉(zhuǎn)換為自己這個(gè)類(這個(gè)其實(shí)是廢話),子類可以向上轉(zhuǎn)換為超類,但超類不能向下(downcast)轉(zhuǎn)換為子類。除非某個(gè)子類的對(duì)象表現(xiàn)形式為超類,但實(shí)際是子類,這時(shí)可以使用as!進(jìn)行向下轉(zhuǎn)換(downcast)。
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")
]
var movieCount = 0
var songCount = 0
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)")
}
}
1.首先試圖將 item 下轉(zhuǎn)為 Movie 。因?yàn)?item 是一個(gè) MediaItem 類型的實(shí)例,它可能是一個(gè) Movie ;同樣,它也可能是一個(gè) Song ,或者僅僅是基類 MediaItem 。因?yàn)椴淮_定, as? 形式在試圖下轉(zhuǎn)時(shí)將返回 一個(gè)可選值。 item as? Movie 的返回值是 Movie? 或者說“可選 Movie ”。
2.當(dāng)向下轉(zhuǎn)型為 Movie 應(yīng)用在兩個(gè) Song 實(shí)例時(shí)將會(huì)失敗。為了處理這種情況,上面的例子使用了可選綁定(op tional binding)來檢查可選 Movie 真的包含一個(gè)值(這個(gè)是為了判斷下轉(zhuǎn)是否成功。)可選綁定是這樣寫 的“ if let movie = item as? Movie ”,可以這樣解讀:
“嘗試將 item 轉(zhuǎn)為 Movie 類型。若成功,設(shè)置一個(gè)新的臨時(shí)常量 movie 來存儲(chǔ)返回的可選 Movie 中的 值”
3.若向下轉(zhuǎn)型成功,然后 movie 的屬性將用于打印一個(gè) Movie 實(shí)例的描述,包括它的導(dǎo)演的名字 directo r 。相似的原理被用來檢測(cè) Song 實(shí)例,當(dāng) Song 被找到時(shí)則打印它的描述(包含 artist 的名字)。
注意
轉(zhuǎn)換沒有真的改變實(shí)例或它的值。根本的實(shí)例保持不變;只是簡(jiǎn)單地把它作為它被轉(zhuǎn)換成的類型來使用。
2.1. as!使用場(chǎng)合
向下轉(zhuǎn)型(Downcasting)時(shí)使用。由于是強(qiáng)制類型轉(zhuǎn)換,如果轉(zhuǎn)換失敗會(huì)報(bào)運(yùn)行錯(cuò)誤。
class Animal {
}
class Cat: Animal {
}
let animal:Animal = Cat()
let cat = animal as! Cat
print("as! --- \(cat)")
2.2. as?使用場(chǎng)合
as? 和 as! 操作符的轉(zhuǎn)換規(guī)則完全一樣。但 as? 如果轉(zhuǎn)換不成功的時(shí)候便會(huì)返回一個(gè) nil 對(duì)象。成功的話返回可選類型值(optional),需要我們拆包使用。
由于 as? 在轉(zhuǎn)換失敗的時(shí)候也不會(huì)出現(xiàn)錯(cuò)誤,所以對(duì)于如果能確保100%會(huì)成功的轉(zhuǎn)換則可使用 as!,否則使用 as?
let animal1:Animal = Cat()
if let cat = animal1 as? Cat{
print("as? --- \(cat)")
}else{
print("cat is nil")
}
