Swift 類型轉(zhuǎn)換

Swift 語(yǔ)言類型轉(zhuǎn)換可以判斷實(shí)例的類型。也可以用于檢測(cè)實(shí)例類型是否屬于其父類或者子類的實(shí)例。

Swift 中類型轉(zhuǎn)換使用 is 和 as 操作符實(shí)現(xiàn),is 用于檢測(cè)值的類型,as 用于轉(zhuǎn)換類型。

類型轉(zhuǎn)換也可以用來(lái)檢查一個(gè)類是否實(shí)現(xiàn)了某個(gè)協(xié)議。


定義一個(gè)類層次

類型轉(zhuǎn)換用于檢測(cè)實(shí)例類型是否屬于特定的實(shí)例類型。

你可以將它用在類和子類的層次結(jié)構(gòu)上,檢查特定類實(shí)例的類型并且轉(zhuǎn)換這個(gè)類實(shí)例的類型成為這個(gè)層次結(jié)構(gòu)中的其他類型。

實(shí)例如下:

class Subjects {
    var physics: String
    init(physics: String) {
        self.physics = physics
    }
}

class Chemistry: Subjects {
    var equations: String
    init(physics: String, equations: String) {
        self.equations = equations
        super.init(physics: physics)
    }
}

class Maths: Subjects {
    var formulae: String
    init(physics: String, formulae: String) {
        self.formulae = formulae
        super.init(physics: physics)
    }
}

let sa = [
    Chemistry(physics: "固體物理", equations: "赫茲"),
    Maths(physics: "流體動(dòng)力學(xué)", formulae: "千兆赫")]


let samplechem = Chemistry(physics: "固體物理", equations: "赫茲")
print("實(shí)例物理學(xué)是: \(samplechem.physics)")
print("實(shí)例方程式: \(samplechem.equations)")


let samplemaths = Maths(physics: "流體動(dòng)力學(xué)", formulae: "千兆赫")
print("實(shí)例物理學(xué)是: \(samplemaths.physics)")
print("實(shí)例公式是: \(samplemaths.formulae)")

以上程序執(zhí)行輸出結(jié)果為:

實(shí)例物理學(xué)是: 固體物理
實(shí)例方程式: 赫茲
實(shí)例物理學(xué)是: 流體動(dòng)力學(xué)
實(shí)例公式是: 千兆赫

檢查類型

類型檢查使用 is 關(guān)鍵字。

操作符 is 來(lái)檢查一個(gè)實(shí)例是否屬于特定子類型。若實(shí)例屬于那個(gè)子類型,類型檢查操作符返回 true,否則返回 false。

class Subjects {
    var physics: String
    init(physics: String) {
        self.physics = physics
    }
}

class Chemistry: Subjects {
    var equations: String
    init(physics: String, equations: String) {
        self.equations = equations
        super.init(physics: physics)
    }
}

class Maths: Subjects {
    var formulae: String
    init(physics: String, formulae: String) {
        self.formulae = formulae
        super.init(physics: physics)
    }
}

let sa = [
    Chemistry(physics: "固體物理", equations: "赫茲"),
    Maths(physics: "流體動(dòng)力學(xué)", formulae: "千兆赫"),
    Chemistry(physics: "熱物理學(xué)", equations: "分貝"),
    Maths(physics: "天體物理學(xué)", formulae: "兆赫"),
    Maths(physics: "微分方程", formulae: "余弦級(jí)數(shù)")]


let samplechem = Chemistry(physics: "固體物理", equations: "赫茲")
print("實(shí)例物理學(xué)是: \(samplechem.physics)")
print("實(shí)例方程式: \(samplechem.equations)")


let samplemaths = Maths(physics: "流體動(dòng)力學(xué)", formulae: "千兆赫")
print("實(shí)例物理學(xué)是: \(samplemaths.physics)")
print("實(shí)例公式是: \(samplemaths.formulae)")

var chemCount = 0
var mathsCount = 0
for item in sa {
    // 如果是一個(gè) Chemistry 類型的實(shí)例,返回 true,相反返回 false。
    if item is Chemistry {
        ++chemCount
    } else if item is Maths {
        ++mathsCount
    }
}

print("化學(xué)科目包含 \(chemCount) 個(gè)主題,數(shù)學(xué)包含 \(mathsCount) 個(gè)主題")

以上程序執(zhí)行輸出結(jié)果為:

實(shí)例物理學(xué)是: 固體物理
實(shí)例方程式: 赫茲
實(shí)例物理學(xué)是: 流體動(dòng)力學(xué)
實(shí)例公式是: 千兆赫
化學(xué)科目包含 2 個(gè)主題,數(shù)學(xué)包含 3 個(gè)主題

向下轉(zhuǎn)型

向下轉(zhuǎn)型,用類型轉(zhuǎn)換操作符(as? 或 as!)

當(dāng)你不確定向下轉(zhuǎn)型可以成功時(shí),用類型轉(zhuǎn)換的條件形式(as?)。條件形式的類型轉(zhuǎn)換總是返回一個(gè)可選值(optional value),并且若下轉(zhuǎn)是不可能的,可選值將是 nil。

只有你可以確定向下轉(zhuǎn)型一定會(huì)成功時(shí),才使用強(qiáng)制形式(as!)。當(dāng)你試圖向下轉(zhuǎn)型為一個(gè)不正確的類型時(shí),強(qiáng)制形式的類型轉(zhuǎn)換會(huì)觸發(fā)一個(gè)運(yùn)行時(shí)錯(cuò)誤。

class Subjects {
    var physics: String
    init(physics: String) {
        self.physics = physics
    }
}

class Chemistry: Subjects {
    var equations: String
    init(physics: String, equations: String) {
        self.equations = equations
        super.init(physics: physics)
    }
}

class Maths: Subjects {
    var formulae: String
    init(physics: String, formulae: String) {
        self.formulae = formulae
        super.init(physics: physics)
    }
}

let sa = [
    Chemistry(physics: "固體物理", equations: "赫茲"),
    Maths(physics: "流體動(dòng)力學(xué)", formulae: "千兆赫"),
    Chemistry(physics: "熱物理學(xué)", equations: "分貝"),
    Maths(physics: "天體物理學(xué)", formulae: "兆赫"),
    Maths(physics: "微分方程", formulae: "余弦級(jí)數(shù)")]


let samplechem = Chemistry(physics: "固體物理", equations: "赫茲")
print("實(shí)例物理學(xué)是: \(samplechem.physics)")
print("實(shí)例方程式: \(samplechem.equations)")


let samplemaths = Maths(physics: "流體動(dòng)力學(xué)", formulae: "千兆赫")
print("實(shí)例物理學(xué)是: \(samplemaths.physics)")
print("實(shí)例公式是: \(samplemaths.formulae)")

var chemCount = 0
var mathsCount = 0

for item in sa {
    // 類型轉(zhuǎn)換的條件形式
    if let show = item as? Chemistry {
        print("化學(xué)主題是: '\(show.physics)', \(show.equations)")
        // 強(qiáng)制形式
    } else if let example = item as? Maths {
        print("數(shù)學(xué)主題是: '\(example.physics)',  \(example.formulae)")
    }
}

以上程序執(zhí)行輸出結(jié)果為:

實(shí)例物理學(xué)是: 固體物理
實(shí)例方程式: 赫茲
實(shí)例物理學(xué)是: 流體動(dòng)力學(xué)
實(shí)例公式是: 千兆赫
化學(xué)主題是: '固體物理', 赫茲
數(shù)學(xué)主題是: '流體動(dòng)力學(xué)',  千兆赫
化學(xué)主題是: '熱物理學(xué)', 分貝
數(shù)學(xué)主題是: '天體物理學(xué)',  兆赫
數(shù)學(xué)主題是: '微分方程',  余弦級(jí)數(shù)

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

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

  • AnyObject可以代表任何class類型的實(shí)例。
  • Any可以表示任何類型,包括方法類型(function types)。

注意:
只有當(dāng)你明確的需要它的行為和功能時(shí)才使用AnyAnyObject。在你的代碼里使用你期望的明確的類型總是更好的。

Any 實(shí)例

class Subjects {
    var physics: String
    init(physics: String) {
        self.physics = physics
    }
}

class Chemistry: Subjects {
    var equations: String
    init(physics: String, equations: String) {
        self.equations = equations
        super.init(physics: physics)
    }
}

class Maths: Subjects {
    var formulae: String
    init(physics: String, formulae: String) {
        self.formulae = formulae
        super.init(physics: physics)
    }
}

let sa = [
    Chemistry(physics: "固體物理", equations: "赫茲"),
    Maths(physics: "流體動(dòng)力學(xué)", formulae: "千兆赫"),
    Chemistry(physics: "熱物理學(xué)", equations: "分貝"),
    Maths(physics: "天體物理學(xué)", formulae: "兆赫"),
    Maths(physics: "微分方程", formulae: "余弦級(jí)數(shù)")]


let samplechem = Chemistry(physics: "固體物理", equations: "赫茲")
print("實(shí)例物理學(xué)是: \(samplechem.physics)")
print("實(shí)例方程式: \(samplechem.equations)")


let samplemaths = Maths(physics: "流體動(dòng)力學(xué)", formulae: "千兆赫")
print("實(shí)例物理學(xué)是: \(samplemaths.physics)")
print("實(shí)例公式是: \(samplemaths.formulae)")

var chemCount = 0
var mathsCount = 0

for item in sa {
    // 類型轉(zhuǎn)換的條件形式
    if let show = item as? Chemistry {
        print("化學(xué)主題是: '\(show.physics)', \(show.equations)")
        // 強(qiáng)制形式
    } else if let example = item as? Maths {
        print("數(shù)學(xué)主題是: '\(example.physics)',  \(example.formulae)")
    }
}

// 可以存儲(chǔ)Any類型的數(shù)組 exampleany
var exampleany = [Any]()

exampleany.append(12)
exampleany.append(3.14159)
exampleany.append("Any 實(shí)例")
exampleany.append(Chemistry(physics: "固體物理", equations: "兆赫"))

for item2 in exampleany {
    switch item2 {
    case let someInt as Int:
        print("整型值為 \(someInt)")
    case let someDouble as Double where someDouble > 0:
        print("Pi 值為 \(someDouble)")
    case let someString as String:
        print("\(someString)")
    case let phy as Chemistry:
        print("主題 '\(phy.physics)', \(phy.equations)")
    default:
        print("None")
    }
}

以上程序執(zhí)行輸出結(jié)果為:

實(shí)例物理學(xué)是: 固體物理
實(shí)例方程式: 赫茲
實(shí)例物理學(xué)是: 流體動(dòng)力學(xué)
實(shí)例公式是: 千兆赫
化學(xué)主題是: '固體物理', 赫茲
數(shù)學(xué)主題是: '流體動(dòng)力學(xué)',  千兆赫
化學(xué)主題是: '熱物理學(xué)', 分貝
數(shù)學(xué)主題是: '天體物理學(xué)',  兆赫
數(shù)學(xué)主題是: '微分方程',  余弦級(jí)數(shù)
整型值為 12
Pi 值為 3.14159
Any 實(shí)例
主題 '固體物理', 兆赫

AnyObject 實(shí)例

class Subjects {
    var physics: String
    init(physics: String) {
        self.physics = physics
    }
}

class Chemistry: Subjects {
    var equations: String
    init(physics: String, equations: String) {
        self.equations = equations
        super.init(physics: physics)
    }
}

class Maths: Subjects {
    var formulae: String
    init(physics: String, formulae: String) {
        self.formulae = formulae
        super.init(physics: physics)
    }
}

// [AnyObject] 類型的數(shù)組
let saprint: [AnyObject] = [
    Chemistry(physics: "固體物理", equations: "赫茲"),
    Maths(physics: "流體動(dòng)力學(xué)", formulae: "千兆赫"),
    Chemistry(physics: "熱物理學(xué)", equations: "分貝"),
    Maths(physics: "天體物理學(xué)", formulae: "兆赫"),
    Maths(physics: "微分方程", formulae: "余弦級(jí)數(shù)")]


let samplechem = Chemistry(physics: "固體物理", equations: "赫茲")
print("實(shí)例物理學(xué)是: \(samplechem.physics)")
print("實(shí)例方程式: \(samplechem.equations)")


let samplemaths = Maths(physics: "流體動(dòng)力學(xué)", formulae: "千兆赫")
print("實(shí)例物理學(xué)是: \(samplemaths.physics)")
print("實(shí)例公式是: \(samplemaths.formulae)")

var chemCount = 0
var mathsCount = 0

for item in saprint {
    // 類型轉(zhuǎn)換的條件形式
    if let show = item as? Chemistry {
        print("化學(xué)主題是: '\(show.physics)', \(show.equations)")
        // 強(qiáng)制形式
    } else if let example = item as? Maths {
        print("數(shù)學(xué)主題是: '\(example.physics)',  \(example.formulae)")
    }
}

var exampleany = [Any]()
exampleany.append(12)
exampleany.append(3.14159)
exampleany.append("Any 實(shí)例")
exampleany.append(Chemistry(physics: "固體物理", equations: "兆赫"))

for item2 in exampleany {
    switch item2 {
    case let someInt as Int:
        print("整型值為 \(someInt)")
    case let someDouble as Double where someDouble > 0:
        print("Pi 值為 \(someDouble)")
    case let someString as String:
        print("\(someString)")
    case let phy as Chemistry:
        print("主題 '\(phy.physics)', \(phy.equations)")
    default:
        print("None")
    }
}

以上程序執(zhí)行輸出結(jié)果為:

實(shí)例物理學(xué)是: 固體物理
實(shí)例方程式: 赫茲
實(shí)例物理學(xué)是: 流體動(dòng)力學(xué)
實(shí)例公式是: 千兆赫
化學(xué)主題是: '固體物理', 赫茲
數(shù)學(xué)主題是: '流體動(dòng)力學(xué)',  千兆赫
化學(xué)主題是: '熱物理學(xué)', 分貝
數(shù)學(xué)主題是: '天體物理學(xué)',  兆赫
數(shù)學(xué)主題是: '微分方程',  余弦級(jí)數(shù)
整型值為 12
Pi 值為 3.14159
Any 實(shí)例
主題 '固體物理', 兆赫

在一個(gè)switch語(yǔ)句的case中使用強(qiáng)制形式的類型轉(zhuǎn)換操作符(as, 而不是 as?)來(lái)檢查和轉(zhuǎn)換到一個(gè)明確的類型。