구조체와 클래스의 차이점 중 가장 큰 부분 중 하나가 바로 상속
쉽게 이야기하면, 다른 클래스의 성질을 이어받는 것
정확히는 기존 클래스를 기반으로 기능을 추가하거나 재정의하여 새로운 클래스를 만드는 것
📌 헷갈리는 용어 정리
기존 클래스(상속되는 클래스) = 상위 클래스 = 슈퍼 클래스 = 부모 클래스
상속하는 클래스 = 하위 클래스 = 서브 클래스 = 자식 클래스
이 글은 상위 클래스, 하위 클래스로 통일하여 작성
다른 클래스를 상속하지 않는 클래스
class Vehicle {
var currentSpeed = 0.0
var description: String {
return "현재 속도는 \(currentSpeed)입니다."
}
func makeNoise() {
}
}
let someVehicle = Vehicle()
print(someVehicle.description) // 현재 속도는 0.0입니다.
Vehicle
클래스class Bicycle: Vehicle {
}
나 Bicycle
은 Vehicle
을 상속할 거야! 하고 나타내기
class Bicycle: Vehicle {
}
let bicycle = Bicycle()
print(bicycle.description) // 현재 속도는 0.0입니다.
Bicycle
도 Vehicle
의 멤버에 접근이 가능하다.
class Bicycle: Vehicle {
var hasBasket = true
}
let bicycle = Bicycle()
print(bicycle.description) // 현재 속도는 0.0입니다.
print("바구니 유무:", bicycle.hasBasket) // 바구니 유무: true
bicycle.currentSpeed = 5.0
print(bicycle.description) // 현재 속도는 5.0입니다.
Bicycle
은 Vehicle
의 모든 특성을 자동적으로 얻는다.class MountainBike: Bicycle {
}
let mountainBike = MountainBike()
mountainBike.hasBasket = false
물론 하위 클래스 자체도 다른 클래스에 의해 상속될 수 있다.
override
키워드가 필요ex. 기존의 구현을 구체화하고 싶을 때
super
키워드로 상위 클래스의 해당 메서드, 프로퍼티, 서브스크립트에 접근 가능
class Vehicle {
var currentSpeed = 0.0
var description: String {
return "현재 속도는 \(currentSpeed)입니다."
}
func makeNoise() {
print("소리가 난다... ~")
}
}
class Train: Vehicle {
override func makeNoise() {
print("추추 🚂")
}
}
let train = Train()
train.makeNoise() // 추추 🚂
override
키워드 미작성 시 에러override func makeNoise() {
super.makeNoise()
print("추추 🚂")
}
/*
소리가 난다... ~
추추 🚂
*/
super.makeNoise()
호출 시, 상위 클래스의 makeNoise()
구현 가져오기 가능getter
와 setter
를 통한 재정의getter
와 setter
를 통한 재정의class Vehicle {
var currentSpeed = 0.0
var description: String {
return "현재 속도는 \(currentSpeed)입니다."
}
func makeNoise() {
}
}
class Car: Vehicle {
var gear = 1
override var description: String {
return "기어: \(gear)"
}
}
let car = Car()
print(car.description) // 기어: 1
description
에 접근하고 싶다면 super
사용하기 class Car: Vehicle {
var gear = 1
override var description: String {
return "기어: \(gear), 속도: \(super.description)"
}
}
let car = Car()
car.currentSpeed = 30
print(car.description) // 기어: 1, 속도: 현재 속도는 30.0입니다.
저장 프로퍼티도 마찬가지
setter
가 호출되지 않기 때문에 프로퍼티 옵저버를 추가할 필요가 없음class Car: Vehicle {
var gear = 1
override var description: String {
return "기어: \(gear), 속도: \(super.description)"
}
}
class AutomaticCar: Car {
override var currentSpeed: Double {
didSet {
gear = Int(currentSpeed / 10.0) + 1
}
}
}
let automaticCar = AutomaticCar()
automaticCar.currentSpeed = 30
print(automaticCar.description) // 기어: 4, 속도: 현재 속도는 30.0입니다.
class Vehicle {
var currentSpeed = 0.0
}
class Car: Vehicle {
override var currentSpeed = 3.0
// 🚨 Cannot override with a stored property 'currentSpeed'
}
final
표시를 통해 재정의 방지 가능class Vehicle {
var currentSpeed = 0.0
final var description: String {
return "현재 속도는 \(currentSpeed)입니다."
}
func makeNoise() {
}
}
class Car: Vehicle {
var gear = 1
override var description: String { //🚨 error: property overrides a 'final' property
return super.description + "\(gear)"
}
}
description
프로퍼티 앞에 final
키워드를 붙여 재정의가 불가하다고 표시final class Vehicle {
var currentSpeed = 0.0
var description: String {
return "현재 속도는 \(currentSpeed)입니다."
}
func makeNoise() {
}
}
class Car: Vehicle { // 🚨 inheritance from a final class 'Vehicle'
}
UIViewController
클래스를 상속하는 ViewController
UIViewController
의 viewdidLoad
를 재정의super.viewDidLoad()
를 호출함으로써 상위 클래스 UIViewController
의 viewDidLoad()
도 그대로 받아오기