타입 캐스팅(Type Casting)은 인스턴스의 타입을 확인해주는 기능과 클래스의 인스턴스를 상위 클래스 타입으로 또는 하위 클래스 타입으로 취급해주는 기능이 있습니다.
is
연산자는 인스턴스의 타입을 확인해주는 기능을 가지고 있는 연산자입니다.
인스턴스가 가지고 있는 프로퍼티가 해당 타입(클래스, 구조체 등)의 프로퍼티를 포괄하면 true를 반환하지만, 그렇지 않으면 false을 반환합니다.
✅ is 연산자를 사용하여 인스턴스 타입을 검사
클래스 인스턴스 사용 가능한 프로퍼티 A x a B(A 클래스를 상속) y a, b C(B 클래스를 상속) z a, b, c class A{ var a: Int = 1 } class B:A{ var b: Int = 2 } class C:B{ var c: Int = 3 } var x = A() var y = B() var z = C() print(x is B) // false 인스턴스 x는 프로퍼티 b 없음 print(x is C) // false 인스턴스 x는 프로퍼티 b, c 없음 print(y is A) // true 인스턴스 y는 A클래스의 모든 프로퍼티 사용 가능 print(y is C) // false 인스턴스 y는 프로퍼티 c 없음 print(z is A) // true 인스턴스 z는 A클래스의 모든 프로퍼티 사용 가능 print(z is B) // true 인스턴스 z는 B클래스의 모든 프로퍼티 사용 가능
as
연산자에는 업캐스팅(Upcasting)과 다운캐스팅(Downcasting)이 존재합니다.
업캐스팅(Upcasting)은 특정 하위 클래스의 인스턴스를 상위 클래스 타입으로 변경하는 개념입니다.
다운캐스팅(Downcasting)은 특정 상위 클래스의 인스턴스를 하위 클래스 타입으로 변경하는 개념입니다.
✅ as 연산자를 사용하여 인스턴스를 상위 클래스로 업캐스팅(Upcasting)
- 업캐스팅은 실패 가능성이 없으므로 옵셔널 타입으로 반환되지 않습니다. (하위 인스턴스는 상위 클래스로부터 상속받아 정의되었기 때문)
- 업캐스팅시 접근할 수 있는 멤버의수가 줄어듭니다. 이는 하위 클래스로부터 만들어진 인스턴스를 상위 클래스 타입으로 인식하기 때문입니다. (메모리값 변동은 없음)
var(let) 새로운 인스턴스명 = 하위(자식) 인스턴스: 상위(부모) 클래스
class A{ var a: Int = 1 func aaa(){ print("저는 a입니다.") } } class B: A{ var b: Int = 2 override func aaa(){ print("저는 a(class B: A)입니다.") } func bbb(){ print("저는 b입니다.") } } class C: B{ var c: Int = 3 override func aaa(){ print("저는 a(class C: B)입니다.") } override func bbb(){ print("저는 b(class C: B)입니다.") } func ccc(){ print("저는 c입니다.") } } var kim = A() kim.aaa() //저는 a입니다. var lee = B() lee.aaa() //저는 a(class B: A)입니다. lee.bbb() //저는 b입니다. var park = C() park.aaa() //저는 a(class C: B)입니다. park.bbb() //저는 b(class C: B)입니다. park.ccc() //저는 c입니다. var kim2 = lee as A kim2.aaa() //저는 a(class B: A)입니다. var lee2 = park as B lee2.aaa() //저는 a(class C: B)입니다. lee2.bbb() //저는 b(class C: B)입니다.
✅ as? / as! 연산자를 사용하여 인스턴스를 하위 클래스로 다운캐스팅(Downcasting)
- 다운캐스팅은 실패 가능성이 있으므로 옵셔널 타입으로 반환됩니다. (상위 클래스에서 하위 클래스의 프로퍼티가 정의되지 않을 수 있기 때문)
- 다운캐스팅시 접근할 수 있는 멤버의 수가 증가합니다. 이는 상위 클래스로부터 만들어진 인스턴스를 하위 클래스 타입으로 인식하기 때문입니다. (상위 클래스보다 하위클래스의 멤버가 많습니다.)
var(let) 새로운 인스턴스명 = 상위(부모) 인스턴스: 하위(자식) 클래스
class A{ var a: Int = 1 func aaa(){ print("저는 a입니다.") } } class B: A{ var b: Int = 2 override func aaa(){ print("저는 a(class B: A)입니다.") } func bbb(){ print("저는 b입니다.") } } class C: B{ var c: Int = 3 override func aaa(){ print("저는 a(class C: B)입니다.") } override func bbb(){ print("저는 b(class C: B)입니다.") } func ccc(){ print("저는 c입니다.") } } var kim = A() kim.aaa() //저는 a입니다. var lee = B() lee.aaa() //저는 a(class B: A)입니다. lee.bbb() //저는 b입니다. var park = C() park.aaa() //저는 a(class C: B)입니다. park.bbb() //저는 b(class C: B)입니다. park.ccc() //저는 c입니다. if let kim2 = kim as? B{ print(kim2.b) //nil } if let lee2 = lee as? C{ print(lee2.c) //nil }
참고자료: 앨런 Swift문법 마스터 스쿨