인스턴스의 타입을 확인하거나 어떠한 클래스의 인스턴스를 해당 클래스 계층 구조의 슈퍼 클래스나 서브 클래스로 취급하는 방법
다음과 같이 MediaItem
을 타입으로 하는 Movie
클래스와 Song
클래스가 있다고 하자.
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)
}
}
이때, 이 두개의 클래스에 대해 for ... in
구문 안에서 is
연산자를 통해 각 엘리먼트에 대한 타입을 추론하는 것이 가능하다.
let library = [
Movie(name: "기생충", director: "봉준호"),
Song(name: "Butter", artist: "BTS"),
Movie(name: "올드보이", director: "박찬욱"),
Song(name: "Wonderwall", artist: "Oasis"),
Song(name: "Next Level", artist: "aespa")
]
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")
// "Media library contains 2 movies and 3 songs"
뿐만 아니라, 조건문에서 하위 클래스의 인스턴스를 참조하는 것도 가능하다. 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 {
pring("Song: \(song.name), by \(song.artist)")
}
}
// Movie: 기생충, dir. 봉준호
// Song: Butter, by BTS
// Movie: 올드보이, dir. 박찬욱
// Song: Wonderwall, by Oasis
// Song: Next Level, by aespa