swift 공식 문서
[iOS - swift 공식 문서] 18. Type Casting (타입 캐스팅, 다운캐스팅, 업캐스팅)
jake-kim
2021. 7. 15. 22:15
Type Casting
- instance의 유형을 확인하거나 해당 instance를 자체 클래스 계층 구조에서 superclass또는 subclass로 처리하는 방법
- 연산자는 두가지: is와 as
Type 확인
- is연산자 사용: 좌측엔 instance, 우측엔 type
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)
}
}
// upcasting: 타입은 superclass이지만 instance는 subclass
let library = [
Movie(name: "name1", director: "dir1"),
Song(name: "name2", artist: "art1"),
Movie(name: "name3", director: "dir2")
]
var movieCount = 0
var songCount = 0
library.forEach { item in
if item is Movie {
movieCount += 1
} else if item is Song {
songCount += 1
}
}
print(movieCount) // 2
print(songCount) // 1
Downcasting
- type은 superlcass지만 subclass의 인스턴스로 type 변경
- 연산자는 두 가지 존재
- as?
- as!
// Type은 MediaItem이지만 subclass인 movie와 song으로 downcasting
library.forEach { item in
if let movie = item as? Movie {
print("movie: \(movie.name)")
} else if let song = item as? Song {
print("song: \(song.name)")
}
}
Upcasting
- type은 subclass지만 superclass의 인스턴스로 type 변경
- as 사용, 무조건 성공 (subclass 타입을 superclass로 변경하는 것이므로)
- as와 is 차이 주의
- is는 instance타입을 확인하는데 사용
- as는 type casting에 사용
let exTeacher: Teacher = Teacher(year: 2021, name: "abc")
let exHuman: Human = Human(name: "a")
/// upcasting: subclass instance를 superclass 타입으로 변경
let human: Human = exTeacher as Human /// 업캐스팅
/// downcasting: superclass instance를 subclass 타입으로 변경
let teacher: Teacher? = exHuman as? Teacher
Any, AnyObject에 대한 Type casting
- Any와 AnyObject 타입을 사용할 경우, 상속 관계가 아니어도 예외적으로 type casting 사용 가능
- 개념 주의: 부모 타입을 자식 타입으로 변경하는 것이므로 downcasting인것 같지만, as로 사용하는 것을 주의
- Any: 모든 type을 포함하여 모든 유형의 instance 나타낼 수 있는 것
- AnyObject: 모든 class type의 instance 표현
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:
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")
}
}
* 참고
https://docs.swift.org/swift-book/LanguageGuide/TypeCasting.html