[Swift] Inheritance
Inheritance
상속은 일단 추가적으로 필요한 데이터(저장 속성)을 늘린다는 관점에서 생각
class Person {
var id = 0
var name = "이름"
var email = "abc@gmail.com"
}
// Person 클래스를 상속받음
class Student: Person {
// id
// name
// email
var studentId = 0
}
// Person 클래스를 상속 받은 Student 클래스를 상속받음
class Undergraduate: Student {
// id
// name
// email
// studentId
var major = "전공"
}
- 기본 클래스 : 다른 어떤 것도 상속하지 않은 클래스
- (상대적으로) 상속 하는 클래스 : 부모 클래스, 슈퍼 클래스, 상위 클래스
- (상대적으로) 상속 받는 클래스 : 자식 클래스, 서브 클래스, 하위 클래스
- 클래스의 상속 금지의 키워드
final
- 경우에 따라서, 클래스의 상속을 금지해야하는 경우가 있음
final
을 각 멤버 앞에 붙인 경우, 해당 멤버 재정의 불가라는 뜻
- 수직 확장 : 본질적으로 성격이 비슷한 타입을 새로 만들어서
- 데이터(저장 속성)를 추가하거나
- 기능(메서드)을 변형시켜 사용하려는 것
- 언어마다 다른데 스위프트는 다중상속을 지원 안함 (파이썬은 지원)
클래스 상속
class Aclass {
func doSomething() {
print("Do something")
}
}
class Bclass: Aclass {
override func doSomething() { // 서브 클래스에서 슈퍼 클래스 함수 재정의
super.doSomething() // 서브 클래스에서 슈퍼 클래스의 메서드 호출
print("Do another job")
}
}
- 오버라이딩(overriding, 재정의)
- 클래스의 상속에서 상위클래스의 속성/메서드를 재정의(기능을 약간 변형해서) 사용하는 것
- 재정의 가능한 대상(멤버)
- 속성 (하지만, 저장 속성에 대한 재정의는 어떠한 경우에도 불가능)
- 메서드 (메서드, 서브스크립트, 생성자)
-> 속성과 메서드는 재정의 방식이 다름
- 저장 속성의 재정의는 원칙적 불가 (데이터 구조의 변형은 불가)
- 서브 클래스에서는 슈퍼 클래스의 속성들의 주소를 가르키기만 하기 때문
오버로딩(overloading, 과적)
함수에서 함수의 하나의 이름에 여러 함수를 대응시켜서 사용
클래스 재정의
// 상위 클래스
class Vehicle1 {
var currentSpeed = 0.0
var datas = ["1", "2", "3", "4", "5"]
func makeNoise() {
print("경적을 울린다.")
}
subscript(index: Int) -> String {
get {
if index > 4 {
return "0"
}
return datas[index]
}
set {
datas[index] = newValue
}
}
}
// 메서드의 재정의 방식
class Bicycle1: Vehicle1 {
// 1) 상위 => 하위 호출 가능
override func makeNoise() {
super.makeNoise()
print("자전거가 지나간다고 소리친다.")
}
// 2) 하위 => 상위 호출 가능
override func makeNoise() {
print("자전거가 지나간다고 소리친다.")
super.makeNoise()
}
// 3) 상위구현 아예 무시 가능
override func makeNoise() {
print("경적을 울리고, 자전거가 지나간다고 소리친다.")
}
// 서브스크립트도 재정의 가능
override subscript(index: Int) -> String {
get {
if index > 4 {
return "777"
}
return super[index]
}
set {
super[index] = newValue
}
}
}
- 저장 속성 재정의 불가
- 저장 속성은 실제 인스턴스에 각각의 멤버별(속성별로) 저장공간이 있고, 변형하는 것이 불가 (상속의 기본 원칙)
- 메서드는 재정의 가능 (기능 확장만 가능, 기능 축소 불가)
(재정의를 하지 않아도, 상속에서는 당연히 모든 멤버의 상속이 일어남)- 메서드는 타입(데이터 영역)에만 배열형태로 주소값을 저장되어 존재하므로 각 상속단계에서 재정의 되고 대체 되는 것이 당연
- 저장 속성
- 재정의 불가
- 메모리 구조에서 상위 구현을 참조하기 때문에 재정의(변형) 불가능
- 예외) 메서드 형태로 부수적 추가는 가능
(메모리 구조를 건드리지 않는 형태로는 가능)- 읽기 / 쓰기 계산속성 형태로 재정의 가능
(메서드 추가 형태로 구현) - 속성 감시자 형태로 재정의 가능
(실질적 단순 메서드 추가)
- 읽기 / 쓰기 계산속성 형태로 재정의 가능
- 재정의 불가
- 계산 속성
- 계산 속성의 재정의는 실질적 메서드 대체
- 확장 방식의 재정의 가능
- 읽기 -> 읽기/쓰기 가능 (기능 확장 가능)
- 읽기/쓰기 -> 읽기 불가능 (기능 축소 불가능)
- 속성 감시자를 추가하는 재정의 가능 (실질적 단순 메서드 추가)
- 생성자
- 생성자는 기본적으로 상속되지 않고 재정의 원칙
(생성자는 모든 저장 속성을 초기화하는 도구이기 때문에, 서브클래스에 최적화 안되어 있음) - 상위 지정 생성자와 현재 단계의 저장 속성을 고려해서 구현
- 예외) 생성자의 자동 상속
- 지정 생성자 / 편의 생성자 자동 상속의 경우 있음
- 생성자는 기본적으로 상속되지 않고 재정의 원칙
- 메서드
- 일반적으로 상위구현의 메서드를 대체 및 변형 할 수도 있으므로, 자유롭게 재정의 가능
(상위 구현을 호출하는 경우도 많으니 주의)
- 일반적으로 상위구현의 메서드를 대체 및 변형 할 수도 있으므로, 자유롭게 재정의 가능