상속 Inheritance
클래스가 다른 클래스로부터 메서드, 프로퍼티 등을 물려받는 것
Class의 상속
- 상속은 클래스에서만 할 수 있다
- 클래스는 단일 상속만 허용한다
- 메서드, 프로퍼티 등 기타 특징을 상속 가능하다
Sub-Classing
- 기존에 있던 클래스를 기반으로 새로운 서브 클래스를 만드는 것 == 상속
class Human {
var name: String?
var age: Int?
var job: String?
}
class Teacher: Human {
var subject: String?
}
- Teacher 클래스는 Human 클래스를 상속받았다
- Human의 멤버인 name, age, job을 사용할 수 있다
let teacher: Teacher = .init()
teacher.name -> Human 클래스의 멤버
teacher.subject -> Teacher 클래스의 멤버
- 상속 할 클래스 == Super Class
- 상속 받을 클래스 == Sub Class
class Yenny: Teacher {
var yen: String = "yeeeeeeeeeeeenny"
}
let yenny: Yenny = .init()
yenny.name -> Human 클래스의 멤버
yenny.subject -> Teacher 클래스의 멤버
yenny.yen -> Yenny 클래스의 멤버
상속 받은 서브 클래스는 상속된 슈퍼 클래스의 멤버(요소)를 전부 사용할 수 있다
서브 클래스에서의 재정의 가능 여부를 정해보자
- final
// 이곳은 Human 클래스의 안
final func sayHello() {
print("hello~")
}
- 서브 클래스에서의 재정의 불가능
- override 불가능
- static
// 이곳은 Human 클래스의 안
static func staticMethod() {
print("type method - static")
}
- 서브 클래스에서의 재정의 불가능
- override 불가능
- class
// 이곳은 Human 클래스의 안
class func classMethod() {
print("type method - class")
}
- 서브 클래스에서의 재정의 가능
- override 가능
- final class
// 이곳은 Human 클래스의 안
final class func finalClassMethod() {
print("type method - final class")
}
- 서브 클래스에서의 재정의 불가능
- override 불가능
- static과 같은 역할
Overriding 오버라이딩
- 서브클래스가 슈퍼 클래스에서 상속받은 인스턴스/타입 메소드, 인스턴스/타입 프로퍼티를 구현할 수 있는 것
- 뜻 == 재정의
- override 키워드를 앞에 붙여주어야 한다
- 메서드 오버라이딩
class Teacher: Human {
var subject: String?
override func selfIntroduce() {
print("My name is \(name) and subject is \(subject)!")
}
override class func classMethod() {
print("재정의를 했음 / type method - class")
}
}
- 프로퍼티 오버라이딩
- 저장/연산 프로퍼티 둘 다 연산작업(getter, setter)를 추가할 수 있음
- 프로퍼티 감시자를 추가할 수 있음
- 반드시 프로퍼티의 이름과 타입을 명시해주기
ㄴ 저장 프로퍼티
- 저장 프로퍼티는 기본적으로 getter와 setter를 전부 가집니다
class Human {
var name = "yenny"
}
- 그런데 만약, 오버라이딩한 서브 클래스에서 getter만 가능하게 구현한다면? ---> ERROR
class Teacher: Human {
var alias = "yenny22222"
// getter
override var name: String {
return self.alias
}
}
- ERROR 원인 -> 슈퍼 클래스에 (저장 프로퍼티이기 때문에) get, set이 구현되어 있는데 왜 멋대로 get만 사용할 수 있게 오버라이딩 시킴? 너 밴.
class Teacher: Human {
var alias = "yenny22222"
override var name: String {
get {
return self.alias
}
set {
self.alias = newValue
}
}
}
- getter 와 setter 를 모두 사용하게 오버라이딩 해주면 된다
let human: Human = .init()
let teacher: Teacher = .init()
human.name -> yenny
teacher.name -> yenny22222
ㄴ 연산 프로퍼티
- 저장 프로퍼티와 특징은 같다
- get만 구현된 슈퍼클래스의 연산 프로퍼티라면, 서브 클래스에서 get과 set을 전부 오버라이딩 할 수 있다
- get,set이 둘다 구현된 슈퍼 클래스를 상속받았다면, 서브 클래스에서 get이나 set 하나만 재정의 할 수 없다 (둘 다 재정의 필요)
class Human {
var name = "yenny"
// getter만 구현된 연산 프로퍼티
let alias: String {
return self.name + "입니다👍"
}
}
// get 만 추가 구현하는 오버라이딩
class Teacher {
override let alias: String {
return self.name + "아닙니다❌❌❌"
}
}
// get, set 둘 다 추가 구현하는 오버라이딩
class Teacher {
override let alias: String {
get {
return self.name + "아닙니다❌❌❌"
}
set {
self.name = newValue
}
}
}
- 프로퍼티 감시자 (프로퍼티 옵저버)
- 반드시 프로퍼티의 이름과 타입을 명시해주기
- 저장 프로퍼티 -> var 로 선언된 프로퍼티라면, 오버라이딩으로 프로퍼티 감시자 추가 가능
- 상수면 값이 변할 일이 없기 때문에 애초에 옵저버를 쓸 이유가 ...? 없습니다👀
class Human {
var age: Int = 0
}
class John {
override var age: Int {
willSet {
print("값 변경 직전에 실행")
}
didSet {
print("값 변경 직후에 실행")
}
}
}
let john: John = .init()
// 값 변경 직전에 실행 -> 0
john.age = 200
// 값 변경 직후에 실행 -> 200
- 연산 프로퍼티 -> get, set이 모두 구현되었다면, 오버라이딩으로 프로퍼티 감시자 추가 가능
class Subject {
var subject: String = "물리"
var alias: String {
get {
return subject + "어려워요😡"
}
set {
self.subject = newValue
}
}
}
class Tom {
override var alias: String {
willSet {
print("값 변경 직전에 실행")
}
didSet {
print("값 변경 직후에 실행")
}
}
}
let top: Tom = .init()
// 값 변경 직전에 실행
john.subject = "화학"
// 값 변경 직후에 실행
오버라이딩에서의 Final
- 오버라이딩을 금지시키는 키워드
- 서브 클래스에서 접근은 할 수 있지만, 재정의는 할 수 없음!
> https://yy-dev.tistory.com/49#-%20final-1
전체 예시
class Human {
var name: String?
var age: Int?
var job: String?
func selfIntroduce() {
print("My name is \(name)!")
}
final func sayHello() {
print("hello~")
}
static func staticMethod() {
print("type method - static")
}
class func classMethod() {
print("type method - class")
}
final class func finalClassMethod() {
print("type method - final class")
}
}
class Teacher: Human {
var subject: String?
override func selfIntroduce() {
print("My name is \(name) and subject is \(subject)!")
}
override class func classMethod() {
print("재정의를 했음 / type method - class")
}
}
let john: Human = .init()
let tom: Teacher = .init()
john.name = "조나단"
tom.name = "토마스"
tom.subject = "과학"
// john.subject = "수학"
// ㄴ ERROR::john은 Human클래스를 타입으로 갖기 떄문에 subject 프로퍼티를 가지지 않음
john.selfIntroduce()
// ---> My name is 조나단!
tom.selfIntroduce()
// ---> My name is 토마스 and subject is 과학!
john.classMethod()
// ---> type method - class
tom.classMethod()
// ---> 재정의를 했음 / type method - class
//재정의 불가능한 멤버들
tom.sayHello()
// ---> hello~
tom.staticMethod()
// ---> type method - static
tom.finalClassMethod()
// ---> type method - final class
'iOS > Swift' 카테고리의 다른 글
[Swift] 고차함수(2/3) reduce(_:_:) (0) | 2023.11.23 |
---|---|
[Swift] 고차함수(1/3) map (0) | 2023.11.23 |
[Swift] 프로퍼티 감시자 Property Observer (0) | 2023.11.21 |
[Swift] ARC/strong/weak/reference cycles(참조 순환) (1) | 2023.11.20 |
[Swift] 연산 프로퍼티 Computed Property (1) | 2023.11.20 |