swift
swift - Inheritance and Polymorphism #1 (Inheritance, Final Class, override, Upcasting, Downcasting)
행복하게사는게꿈
2021. 1. 12. 12:34
Inheritance
네 군데 모두 동일한 속성을 선언하면 매우 불합리한 코딩
공유되는 속성을 하나 선언하고 네개의 클래스가 하나의 속성을 상속받아서 사용
swift는 다중상속을 지원하지 않고 protocal을 사용해서 해결
// BaseClass
class Figure {
var name = "Unknown"
init(name: String) {
self.name = name
}
func draw() {
print("draw \(name)")
}
}
class Cirlce: Figure {
var radius = 0.0
var diameter: Double {
return radius
}
override func draw() {
super.draw()
print("radius \(radius)")
}
}
let c = Cirlce(name: "jaeho") // 상속받은 init사용
c.radius
c.name // 상속받은 속성 사용
c.draw() // 상속받은 메소드 override해서 사용
// 속성 override 하는 방법
// 1. computed property 방식
class Oval: Cirlce {
override var radius: Double {
// 읽기, 쓰기 모두 되는 속성인 경우
get {
return super.radius
}
set {
super.radius = newValue
}
}
override var diameter: Double {
get {
return super.diameter
}
set {
super.radius = newValue / 2
// 읽기전용 속성에는 값을 set할수 없고 다른 속성에 set하게 만들 수 있음
// super.diameter = 11
}
}
}
// 2. property observer 방식
class Oval2: Cirlce {
override var radius: Double {
willSet {
print(newValue)
}
didSet {
print(oldValue)
}
}
// read-only속성은 값을 감시할 수가 없다 -> 즉 읽기전용에서는 property observer방식 불가능
// override var diameter: Double {
// willSet {
// print(newValue)
// }
// didSet {
// print(oldValue)
// }
// }
}
// 클래스를 상속 하게 할 수 있고 특정 메소드를 override 금지시키기
// 금지하고 싶은 변수, 메소드에 final 키워드 추가
final class Rectangle: Figure {
var width = 0.0
var height = 0.0
}
// final class는 상속이 금지된 클래스임
class Square: Rectangle {
}
Upcasting
서브 클래스 인스턴스를 슈퍼 클래스 형식으로 저장
class Rectangle: Figure {
var width = 0.0
var height = 0.0
override func draw() {
super.draw()
print("😀 \(width) x \(height)")
}
}
class Square: Rectangle {
}
let f = Figure(name: "Unknown")
f.name
let r = Rectangle(name: "Rect")
r.width
r.height
r.name
// Upcasting
// 서브 클래스 인스턴스를 슈퍼클래스 형식으로 저장
let s: Figure = Square(name: "Square")
s.height
s.name
s.width
s.draw()
이 상태에서는 밑에 그림처럼 width, height도 메모리 공간에 생성되긴 하지만 Figure클래스의 name에만 접근 할 수 있는 형태이다.
Downcasting
// Downcasting
// Upcasting된 인스턴스를 원래 형식으로 처리하기 위해 필요
// 항상 성공하는게 아님
let downcastedS = s as! Square
downcastedS.name
downcastedS.width
downcastedS.height
class Rhombus: Square {
var angle = 45.0
}
let dr = s as! Rhombus
s라는 Figure 클래스에는 name, width, height가 있는데 Rhombus로 downcasting하려면 err가 발생한다.
왜? Rhombus에 선언된 angle이라는 변수는 Figure 클래스에 존재하지 않기 때문에