이번에는 Type Casting을 통해 인스턴스 형식을 확인하고 다른 형식으로 캐스팅하는 방법을 알아보도록 하겠습니다.
class Figure {
let name: String
init(name: String) {
self.name = name
}
func draw() {
print("draw \(name)")
}
}
class Triangle: Figure {
override func draw() {
super.draw()
print("🍓")
}
}
class Rectangle: Figure {
var width = 0.0
var height = 0.0
override func draw() {
super.draw()
print("🍏 \(width) x \(height)")
}
}
class Square: Rectangle {
}
class Circle: Figure {
var radius = 0.0
override func draw() {
super.draw()
print("🍒")
}
}
let t = Triangle(name: "Triangle")
let r = Rectangle(name: "Rect")
let s = Square(name: "Square")
let c = Circle(name: "Circle")
// expr is Type 타입 체크 연산자 is
r is Rectangle // true
r is Figure // true
r is Square // false
t as? Triangle
t as! Triangle // 원래 형식으로 캐스팅하면 정상적으로 실행됩니다.
var upcasted: Figure = s
// s = Square 입니다.
upcasted = s as Figure // 위와 같음.
upcasted as? Square
upcasted as! Square
upcasted as? Rectangle
upcasted as! Rectangle // 원래 형식의 슈퍼클래스로 다운캐스팅하는 것도 성공합니다.
upcasted as? Circle // nil, 직접적인 상속관계가 없어서 nil을 리턴합니다.
// upcasted as! Circle 에러!!
if let c = upcasted as? Circle {
} // 옵셔널 바인딩과 함께 사용하는 것이 좋습니다.
let list = [t, r, s, c]
for item in list {
item.draw()
if let c = item as? Circle {
c.radius
}
}
// 업캐스팅 되어 있는 인스턴스를 통해서 메소드를 호출하더라도 실제 형식에서 오버라이딩한 메소드가 호출됩니다.