首页 > 代码库 > 十七、类型绑定 Type Casting

十七、类型绑定 Type Casting

1. 概述

Type Casting 的作用:

  • 1)检查某个实例的类型。使用 is 关键字。
  • 2)将某个实例的类型绑定为其他类型来访问。使用 as 关键字。
  • 3)检查某种类型是否实现了协议的方法。

2. 引例,定义三个类:

    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")    ]    // the type of "library" is inferred to be [MediaItem]

 

2.1 检查实例的类型 Checking Type

使用类型检查操作符(type check operatoris 判断一个实例是否是子类类型。如果是子类类型返回 true,否则返回 false。

遍历上面的数组:

    var movieCount = 0    var songCount = 0    for item in library {      if item is Movie {        ++movieCount      } else if item is Song {        ++songCount      }    }    println("Media library contains \(movieCount) movies and \(songCount) songs")    // prints "Media library contains 2 movies and 3 songs"

 

2.2 向下绑定 Downcasting

一个类实例有时要当做它的子类实例来使用,使用类型绑定操作符(type cast operator) as 来向下绑定到子类类型。

如果你不确定转换是否会成功,使用可选值形式 as? ,如果失败,返回 nil 。

    for item in library {      if let movie = item as? Movie {        println("Movie: ‘\(movie.name)‘, dir. \(movie.director)")      } else if let song = item as? Song {        println("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

注意:类型绑定并没有真的修改实例,仅仅只是把它当做它所绑定的类型来对待和访问。

 

3. 绑定为Any和AnyObject类型 Type Casting for Any and AnyObject

Swift为一些不明确的类型提供了两个特殊的类型别名:

  • 1)AnyObject 可以表示任何类类型的实例(对象类型)。
  • 2)Any 可以表示任何类型,包括函数类型。

 

3.1 AnyObject 类型

比如:

    let someObjects: [AnyObject] = [      Movie(name: "2001: A Space Odyssey", director: "Stanley Kubrick"),      Movie(name: "Moon", director: "Duncan Jones"),      Movie(name: "Alien", director: "Ridley Scott")    ]

因为数组中都是Movie的实例类型(对象类型),我们可以将他们向下绑定直接拆包为非可选的Movie类型

    for object in someObjects {      let movie = object as Movie      println("Movie: ‘\(movie.name)‘, dir. \(movie.director)")    }    // Movie: ‘2001: A Space Odyssey‘, dir. Stanley Kubrick    // Movie: ‘Moon‘, dir. Duncan Jones    // Movie: ‘Alien‘, dir. Ridley Scott

也可以使用更简洁的方式——将数组 someObjects的[AnyObject]类型 向下绑定为 [Movie]类型:

    for movie in someObjects as [Movie] {      println("Movie: ‘\(movie.name)‘, dir. \(movie.director)")    }    // Movie: ‘2001: A Space Odyssey‘, dir. Stanley Kubrick    // Movie: ‘Moon‘, dir. Duncan Jones    // Movie: ‘Alien‘, dir. Ridley Scott

 

3.2 Any 类型

比如:

    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)" })

遍历数组:

    for thing in things {      switch thing {        case 0 as Int:          println("zero as an Int")        case 0 as Double:          println("zero as a Double")        case let someInt as Int:          println("an integer value of \(someInt)")        case let someDouble as Double where someDouble > 0:          println("a positive double value of \(someDouble)")        case is Double:          println("some other double value that I don‘t want to print")        case let someString as String:          println("a string value of \"\(someString)\"")        case let (x, y) as (Double, Double):          println("an (x, y) point at \(x), \(y)")        case let movie as Movie:          println("a movie called ‘\(movie.name)‘, dir. \(movie.director)")        case let stringConverter as String -> String:          println(stringConverter("Michael"))        default:          println("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

注意:在上面的代码中使用的是强制绑定as而不是可选的绑定as?,因为在在switch的case语句中使用强制的as永远是安全的。

 

参考自:https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/TypeCasting.html#//apple_ref/doc/uid/TP40014097-CH22-ID338

十七、类型绑定 Type Casting