타입 검사
- 타입 검사 오퍼레이터 : is
- 해당 오퍼레이터를 사용해 인스턴스가 특정한 타입 또는 타입의 서브클래스 타입인지 확인 가능하다.
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)
}
}
var movieCount = 0
var songCount = 0
for item in library {
if item is Movie {
movieCount += 1
} else if item is Song {
songCount += 1
}
}
print("Media library contains \(movieCount) movies and \(songCount) songs")
다운캐스팅
- 클래스 타입의 프로퍼티는 사실 서브클래스 인스턴스를 가리키고 있을 수도 있다.
- 이 때 타입 캐스팅 오퍼레이터 (as? 또는 as!)를 사용해 서브클래스 타입으로 다운캐스팅 할 수 있다.
- 다운캐스팅은 실패 가능한 연산이기 때문에 as? 또는 as! 두 가지 연산자를 제공한다.
- as?는 실패 시 nil을 반환하기 때문에 옵셔널 타입을 반환하고, 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)")
}
}
- 캐스팅은 인스턴스를 변경시키지 않는다. 인스턴스는 똑같이 유지된다.
업캐스팅
- 부모 클래스 타입으로의 업캐스팅을 통해 타입 변환도 가능하다.
class Animal { }
class Dog: Animal { }
let myDog = Dog()
let myAnimal = myDog as Animal
- 업캐스팅은 as 키워드로 수행 가능하며 항상 성공한다.
Any와 AnyObject의 타입 캐스팅
- Swift는 구체 타입이 아닌 타입으로 작업할 수 있는 두 가지 특수한 타입을 제공
- Any : 함수 타입을 포한한 어떤 타입의 인스턴스던 표현 가능
- AnyObject : 어떤 클래스의 인스턴스던 표현 가능
- Any와 AnyObject는 꼭 필요한 경우에만 사용.
- 구체 타입을 제공할 수 있다면 제공하는 것이 항상 좋음
- 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)" })
- Any 또는 AnyObject 타입의 구체 타입을 알기 위해선 is 또는 as 패턴 사용 가능.
for thing in things {
switch thing {
case 0 as Int:
print("zero as an Int")
case 0 as Double:
print("zero as a Double")
case let someInt as Int:
print("an integer value of \(someInt)")
case let someDouble as Double where someDouble > 0:
print("a positive double value of \(someDouble)")
case is Double:
print("some other double value that I don't want to print")
case let someString as String:
print("a string value of \"\(someString)\"")
case let (x, y) as (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")
}
}
- Any에 옵셔널 타입을 곧바로 할당할 수 없다.
- 할당하고자 한다면 아래와 같이 타입 캐스팅이 필요.
let optionalNumber: Int? = 3
things.append(optionalNumber)
things.append(optionalNumber as Any)