[Swift] 상속

·2024년 7월 1일
0

Swift 문법

목록 보기
7/16

상속

구조체와 클래스의 차이점 중 가장 큰 부분 중 하나가 바로 상속


쉽게 이야기하면, 다른 클래스의 성질을 이어받는 것
정확히는 기존 클래스를 기반으로 기능을 추가하거나 재정의하여 새로운 클래스를 만드는 것


📌 헷갈리는 용어 정리
기존 클래스(상속되는 클래스) = 상위 클래스 = 슈퍼 클래스 = 부모 클래스
상속하는 클래스 = 하위 클래스 = 서브 클래스 = 자식 클래스

이 글은 상위 클래스, 하위 클래스로 통일하여 작성


기본 클래스

다른 클래스를 상속하지 않는 클래스

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 {

}

BicycleVehicle 을 상속할 거야! 하고 나타내기


class Bicycle: Vehicle {

}

let bicycle = Bicycle()
print(bicycle.description) // 현재 속도는 0.0입니다.

BicycleVehicle 의 멤버에 접근이 가능하다.


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입니다.
  • 하위 클래스에 새로운 프로퍼티나 메서드를 추가할 수 있다.
  • BicycleVehicle모든 특성을 자동적으로 얻는다.

class MountainBike: Bicycle {

}

let mountainBike = MountainBike()
mountainBike.hasBasket = false

물론 하위 클래스 자체도 다른 클래스에 의해 상속될 수 있다.


재정의(override)

  • 하위 클래스는 상위 클래스에서 상속할 프로퍼티, 메서드, 서브스크립트를 다시 정의할 수 있음
  • 이때는 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() 구현 가져오기 가능

프로퍼티 재정의

  1. gettersetter 를 통한 재정의
  2. 프로퍼티 옵저버를 사용하여 재정의

gettersetter 를 통한 재정의

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입니다.

주의할 점

  • getter/setter 모두를 사용하는 연산 프로퍼티를 읽기 전용 프로퍼티로 재정의할 수 없다
    • 저장 프로퍼티도 마찬가지


프로퍼티 옵저버로 재정의하기

  • 상수 저장 프로퍼티나 읽기 전용 계산 프로퍼티는 프로퍼티 옵저버 추가 불가
    • 상수 저장 프로퍼티는 값을 새로 설정할 수 없기 때문에 프로퍼티 옵저버를 추가하는 것이 의미가 없음
    • 읽기 전용 계산 프로퍼티는 값을 변경하는 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
  • UIViewControllerviewdidLoad 를 재정의
  • super.viewDidLoad() 를 호출함으로써 상위 클래스 UIViewControllerviewDidLoad() 도 그대로 받아오기


Reference

상속 (Inheritance)

0개의 댓글

관련 채용 정보