* 정의
- 타입캐스팅이란 인스턴스의 타입을 확인하거나, 현재 인스턴스의 타입을 다른 클래스의 타입처럼 사용하는것을 의미한다.
1. 타입 확인
- is 연산자를 사용하여 타입을 확인할 수 있다. 인스턴스의 타입이 해당 타입인지 비교해서 맞다면 true를 반환해주고 그렇지 않다면 false를 반환해준다.
class Person {
var name: String
var age: Int
init(name: String, age: Int) {
self.name = name
self.age = age
}
}
let person = Person(name: "홍길동", age: 30)
현재 Person이라는 클래스를 만들고 인스턴스를 생성하였다.
if person is Person {
print("Person의 인스턴스가 맞아!")
}
if person.name is String && person.age is Int {
print("프로퍼티 타입이 일치해!")
}
is 연산자를 사용하여 person 인스턴스가 Person 클래스의 인스턴스인지 타입을 확인하고 있다. 뿐 만 아니라 인스턴스내 프로퍼티의 타입 또한 확인이 가능하다.
2. 다운캐스팅
- 특정 클래스 타입의 변수 또는 상수가 원래 인스턴스 타입과 다른 타입일 수 있다. 이때, 다운캐스팅을 통해 해당 클래스로 타입을 되돌릴 수 있다.
class Cafe {
var cafeName = "someCafe"
}
class Coffee: Cafe {
var coffeeName = "americano"
}
class Bread: Cafe {
var breadName = "baguette"
}
let c: Cafe = Coffee()
c.cafeName
c.coffeeName
현재 c상수는 Cafe 타입의 인스턴스를 참조하도록 정의했지만, 실제로는 타입만 Cafe일 뿐 Coffee 인스턴스를 참조 하고 있다. 하지만 실제로 참조하는 인스턴스가 Coffee인데도 불구하고 Coffee의 프로퍼티에 접근하는 것이 불가능하다. 이유는 타입 때문이다. 현재 참조하는 주소가 Cafe이기 때문에 Cafe의 멤버에만 접근할 수 있다. 이럴 때 다운캐스팅을 사용한다면 인스턴스의 원래 타입으로 되돌릴 수 있다. 방법은 두가지 형태로 제공된다.
2 - 1). as!
let cc = c as! Coffee
as! 연산자는 다운캐스팅을 강제한다. 실패했을 경우 오류가 발생하기 때문에 무조건 성공할 것이라는 확신이 들지 않는 다면 조건부 연자인 as? 를 사용하는 것을 권장한다.
2 - 2). as?
if let cc = c as? Coffee {
cc.coffeeName
cc.cafeName
}
as? 연산자를 다운캐스팅에 사용하면 실패를 했을때 nil을 반환한다. 그러나 성공할 경우 옵셔널 타입으로 인스턴스를 반환한다.
3. Any, AnyObject
스위프트는 모든 값들이 항상 특정 타입으로 저장된다. 그러나 모든 타입을 저장할 수 있는 Any가 있고, 모든 클래스 타입을 저장할 수 있는AnyObject가 있다.
let list: [Any] = [1, "2", 3.0]
여러 타입을 한번에 가지는 [Any] 를 선언했다. 데이터의 모든 타입 정보들은 날아가고 오로지 Any의 타입으로만 표현된다.
for item in list2 {
if let str = item as? String {
}
물론 타입캐스팅을 통하여 특정 타입을 반환하는 것도 가능하지만, 이전에 어떤 타입인지 알고 있지 않은 상태라면 컴파일러 오류를 일으킬 가능성이 크기 때문에 되도록 사용을 지양하는 것이 좋다.
class Cafe {
var cafeName = "someCafe"
}
class Coffee {
var coffeeName = "americano"
}
class Bread {
var breadName = "baguette"
}
let cafe = Cafe()
let coffee = Coffee()
let bread = Bread()
var list: [Any] = [cafe, coffee, bread]
for l in list {
switch l {
case let coffee as Coffee:
print(coffee.coffeeName)
case let cafe as Cafe:
print(cafe.cafeName)
case let bread as Bread:
print(bread.breadName)
default:
break
}
}
String타입은 list 변수 안에 존재 하지 않는다. 스위프트는 암시적변환 타입을 제공하지 않기 때문에 반드시 어떤 타입인지 알고 있는 상태에서 타입캐스팅을 사용해야 한다.