类型检查
类型检查是一种检查类实例的方式,或让实例称为他的父类或子类的一种方式,使用is和as操作符实现1.例子
以下定义一个类和一个包含这几个类实例的数组,作为类型检查的例子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.检查类型
类型检查操作符 is 检查一个实例是否属于某个特定子类型,返回true/falsevar 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"
3.向下转型
某类型的一个常量或变量可能代码里可能是属于一个子类,可以用 as 尝试向下转到他的子类型,因为向下转型可能会失败,所有有可选形式 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
4.Any和AnyObject的类型检查
Swift为不确定的类型提供两种类型别名:AnyObject表示任何class类型的实例,Any表示任何类型,除了方法类型4.1AnyObject类型
// 定义一个AnyObject[] 类型的数组并填入三个Movie类型的实例
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实例,可以直接用 as 向下转型到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
// 简化写法
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
4.2Any
// 使用Any类型来混合不同类型一起工作,包括class类型
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"))
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)")
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
类型嵌套
枚举类型常用于实现特定的类或结构体的功能,也能在多种变量类型的环境中方便的定义通用类或结构体来使用,为实现这种功能,Swift允许自定义嵌套类型,在枚举类型、类和结构体中定义支持嵌套的类型在一个类型中嵌套另一个类型,将需要嵌套的类型的定义写在嵌套类型的区域{}内,而且可以根据需要定义多级嵌套
1.类型嵌套实例
// 定义一个结构体BlackjackCard模拟二十一点中的点数,包含2个嵌套定义的枚举类型Suit和Rank
struct BlackjackCard {
// nested Suit enumeration
enum Suit: Character {
case Spades = "♠", Hearts = "♡", Diamonds = "♢", Clubs = "♣"
}
// nested Rank enumeration
enum Rank: Int {
case Two = 2, Three, Four, Five, Six, Seven, Eight, Nine, Ten
case Jack, Queen, King, Ace
struct Values {
let first: Int, second: Int?
}
var values: Values {
switch self {
case .Ace:
return Values(first: 1, second: 11)
case .Jack, .Queen, .King:
return Values(first: 10, second: nil)
default:
return Values(first: self.toRaw(), second: nil)
}
}
}
// BlackjackCard properties and methods
let rank: Rank, suit: Suit
var description: String {
var output = "suit is \(suit.toRaw()),"
output += " value is \(rank.values.first)"
if let second = rank.values.second {
output += " or \(second)"
}
return output
}
}
let theAceOfSpades = BlackjackCard(rank: .Ace, suit: .Spades)
println("theAceOfSpades: \(theAceOfSpades.description)")
// prints "theAceOfSpades: suit is ♠, value is 1 or 11"
2.类型嵌套的引用
在外部对嵌套类型的引用,以被嵌套类型的名字为前缀,加上所要引用的属性名
let heartsSymbol = BlackjackCard.Suit.Hearts.toRaw()
// heartsSymbol is "♡"