<aside> 💡 재정의(overriding) - 현재의 클래스에 맞게 상위 멤버를 변형시키서, 사용 하려는 것

대원칙:

  1. 저장 속성 재정의 불가
  2. 메서드는 자유롭게 재정의 가능(다만, 기능 확장만 가능 - 기능 축소 불가의 의미)

(재정의를 하지 않아도, 상속에서는 당연히 모든 멤버의 상속이 일어남)

</aside>

<aside> 💡 서브클래스에서는 부모클래스에서 상속받은 것을 재정의 할 수 있습니다. 이것을 overriding 이라 부르는데, 오버라이딩은 인스턴스 메소드, 타입 메소드, 인스턴스 프로퍼티, 타입 프로퍼티, 서브스크립트 모두에 대해 가능합니다. 오버라이드를 위해서는 다른 선언 앞에 override키워드를 붙여줍니다. Swift에서는 이 override키워드를 보면 부모에 그 정의가 있는지 확인합니다.

</aside>

Overriding Properties(프로퍼티 오버라이딩 )

<aside> 💡 서브클래스에서는 상속받은 저장된 프로퍼티, 계산된 프로퍼티 모두 오버라이드 가능합니다. 오버라이드시에는 프로퍼티의 이름과 타입을 명시해야합니다. 왜냐하면 서브클래스에서는 단순히 상속받은 특정 형의 프로퍼티가 있다는 정도만 알고 있기 때문입니다. 상속받은 읽기전용(read only) 프로퍼티도 getter/setter를 정의해서 읽고/쓰기가 가능한(read-write) 프로퍼티로 변경해서 제공 가능합니다. 하지만 반대의 읽고/쓰기가 가능한 프로퍼티를 읽기전용 프로퍼티로 선언하는 것은 할 수 없습니다. 만약 setter를 오버라이드 해서 제공한다면 반드시 getter도 제공해야 합니다.

</aside>

class 탈것 {
    var 경적소리 = "빵"
}

class 자동차: 탈것 {
    var 경적횟수: Int = 2
    override var 경적소리: String {
        get {
            var 자동차경적소리 = ""
            for _ in 0..<경적횟수 {
                자동차경적소리 += super.경적소리
            }
            return 자동차경적소리
        }
        set {
            super.경적소리 = newValue
        }
    }
}

let vehicle = 탈것()
let car = 자동차()

print(car.경적소리) // 빵빵
// 참조타입이므로 외부에서 super 클래스의 프로퍼티를 달라고해도 car 내부에서 구현된 상태로 나온다.
print((car as 탈것).경적소리) // 빵빵
print(vehicle.경적소리) // 빵

Overriding Methods(메서드 오버라이딩)

class Train: Vehicle {
    override func makeNoise() {
        print("Choo Choo")
    }
}

let train = Train()
train.makeNoise()
// Prints "Choo Choo" : 새로 정의한 내용이 출력됩니다.

Overriding Property Observers(프로퍼티 옵저버 오버라이딩)

상수 프로퍼티와 읽기전용 프로퍼티에는 옵저버를 붙일 수 없습니다. 이 프로퍼티는 정의 그대로 set을 할 수 없는 프로퍼티이기 때문입니다. 또 같은 프로퍼티에 옵저버를 추가하고 setter를 추가해 둘을 동시에 사용할 수 없습니다. 이미 setter를 설정했다면 옵저버를 붙인 것과 같은 동작을 하기 때문입니다.

class 특이한자동차: 자동차 {
    override var 경적횟수: Int {
        didSet {
            경적소리 = "뿡"
        }
    }
}

let specialCar = 특이한자동차()

// 경적횟수를 지정해주면, 알아서 경적소리를 뿡으로 바꿈
specialCar.경적횟수 = 3
print(specialCar.경적소리) // 뿡뿡뿡