Swift-型別轉換TypeCasting

Swift-型別轉換TypeCasting

1⃣ 型別轉換是一種檢查實體型別的方法,或者將該實體視為與其自身類別在階層架構中其他位置不同的父類別或子類別。

2⃣ Swift 中的型別轉換是通過is 和 as運算符實做的。這兩個運算符提供了一種簡單而富有表現力的方式來檢查值的型別或將值強制轉換成不同的型別。

3⃣ 還可以使用型別轉換來檢查型別是否符合協定

替型別轉換定義類別的層次結構 Defining a Class Hierarchy for Type Casting

🔴 範列:

// 定義媒體項目類別
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]

library[2].name
// Citizen Kane

檢查型別 Checking Type

🔴 範例:

var movieCount = 0
var songCount = 0

for item in library {
    // 檢查item是否為由Movie類別初始化的實體
    if item is Movie {
        movieCount += 1
    // 檢查item是否為由Song類別初始化的實體
    } else if item is Song {
        songCount += 1
    }
}

print("Media library contains \(movieCount) movies and \(songCount) songs")

向下轉型 Downcasting

💦 當常數或變數的某個類別的型別時,實際上可能在幕後引用(實際的記憶體配置)的是某一個特定子類別的實體。
💦 以嘗試使用型別轉換的運算符號(向下轉換 as? 或 as! )為子類類型。
💦 因為向下轉換可能會失敗,所以型別轉換運算符號有兩種不同的形式。
💦 條件形式 ,as?回傳嘗試向下轉型的型別的選擇值。
💦 強制形式 ,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)")
    }
}

// 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

🔴 範例:

for item in library{
    if item is Movie{
        let movie = item as! Movie
        // as 沒有 ! movie.不出東西
        print("Movie: \(movie.name),dir. \(movie.director)")
    }else if let song = item as? Song {
        // as 沒有 ? song.不出東西
        print("Song: \(song.name), by \(song.artist)")
    }
}

向上轉型(轉回其所屬父類別)

🔴 範例:

let abc = Movie(name: "kkk", director: "ttt")
(abc as MediaItem).name
//kkk

Any 和 AnyObject 的型別轉換 Type Casting for Any and AnyObject

Swift 提供了兩種”特殊型別”來處理非特定型別:

  1. Any可以表示任何型別的實體,包括函式型別、結構、列舉、類別、協定。
  2. AnyObject可以表示任何類別型別的實體。

Any和AnyObject只有在確定需要它們提供的行為和功能時才去使用。最好具體說明希望在程式碼中使用的型別。

🔴 範例:

var things: [Any] = []

things.append(0) //Int的0
things.append(0.0)  // Doble的0
things.append(42)   // Int的42
things.append(3.14159)  // Doble的3.14159 π
things.append("hello")  // String的hello
things.append((3.0, 5.0))   //Tuple型別(double,dobule)的
things.append(Movie(name: "Ghostbusters", director: "Ivan Reitman")) // Movie的型別
things.append({ (name: String) -> String in "Hello, \(name)" }) // 函式型別(String)->String


for thing in things {
    switch thing {
    case 0 as Int:
        print("zero as an Int")
        //攔截Double的0
    case 0 as Double:
        print("zero as a Double")
    case let someInt as Int:
        print("an integer value of \(someInt)")
        // 攔截大於0的Duble
    case let someDouble as Double where someDouble > 0:
        print("a positive double value of \(someDouble)")
        // 攔截小於0的Duble
    case is Double:
        print("some other double value that I don't want to print")
        // 小於等於 0 的 Duble ,攔截String
    case let someString as String:
        print("a string value of \"\(someString)\"")
    case let (x, y) as (Double, Double):
        // 攔截 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