카테고리 없음

Swift 공식 문서 정리 - (13) Inheritance

꾸럽 2023. 4. 28. 15:41

Inheritance (상속)

클래스는 메소드, 프로퍼티와 같은 것들을 다른 클래스로부터 상속할 수 있음

클래스가 다른 타입과 구분되는 근본적 요소임

클래스는 상위 클래스에 속하는 메소드, 프로퍼티 및 서브스크립트를 호출하고 액세스 할 수 있으며

오버라이드 버전을 제공하여 동작을 구체화 하거나 수정할 수 있음

클래스에서는 프로퍼티 종류(저장, 계산된) 과 상관없이 상속받은 프로퍼티 옵저버를 설정해서

값 설정에 반응 할 수 있음

기반 클래스 정의

다른 클래스에서 상속하지 않는 모든 클래스를 기반 클래스라고 함

class Vehicle {
    var currentSpeed = 0.0
    var description: String {
        return "traveling at \\(currentSpeed) miles per hour"
    }
    func makeNoise() {
        // do nothing - an arbitrary vehicle doesn't necessarily make a noise
    }
}

위의 예제에서 현재속도를 프로퍼티로 갖고 있고, description을 계산된 프로퍼티로 선언함

makeNoise()라는 메소드도 가지고 있음.

// 생성
let someVehicle = Vehicle()

print("Vehicle: \\(someVehicle.description)")
// Vehicle: traveling at 0.0 miles per hour

서브클래싱

상속, 다시말해 서브클래싱을 하면 부모로 부터 성격을 상속받고 자기 자신의

고유 특성도 추가할 수 있음

서브클래싱해 새 클래스를 선언하는 코드는 다음과 같음

class SomeSubclass: SomeSuperclass {
    // subclass definition goes here
}

// :SomeSuperclass 로 상속을 선언할 수 있으

위 탈것을 서브클래싱해 자전거 라는 클래스를 선언하면 코드는 다음과 같음

class Bicycle: Vehicle {
    var hasBasket = false
}

Bicycle 은 Vehicle 서브클래싱 하고 자기 자신의 프로퍼티 hasBasket 도 추가함

let bicycle = Bicycle()
bicycle.hasBasket = true

bicycle.currentSpeed = 15.0
print("Bicycle: \\(bicycle.description)")
// Bicycle: traveling at 15.0 miles per hour

Bicycle 객체를 생성해 고유 프로퍼티를 사용할 수 있는 것을 확인

currentSpeed, description 프로퍼티도 사용 가능

서브클래스로 생성된 클래스를 다시 서브클래싱 하는 것도 가능

class Tandem: Bicycle {
    var currentNumberOfPassengers = 0
}

오버라이딩 ( Overriding )

서브클래스에서는 부모클래스에서 상속 받은 것을 재정의 할 수 있음

오버라이딩은 인스턴스-타입 메소드, 인스턴스-타입 프로퍼티, 서브스크립트 모두 가능

오버라이드를 위해서는 다른 선언 앞에 override 키워드를 붙여 줌

부모클래스의 메소드, 프로퍼티, 서브스크립트의 접근

super 키워드와 점문법 혹은 인덱스 구문으로 부모 클래스의 메소드, 프로퍼티, 서브스크립트에 접근 가능

메소드 오버라이드

상속 받은 메소드를 오버라이드 하기 위해서는 메소드 선언 앞에 override 키워드 붙이기

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

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

프로퍼티 오버라이드

상속된 프로퍼티가 저장, 계산된 프로퍼티 여부에 관계없이 상속된 프로퍼티를 재정의하기 위해 사용자 지정 getter, setter를 제공할 수 있음

상속된 프로퍼티는 하위 클래스에서 알 수 없음. 상속된 프로퍼티에 특정 이름과 타입이 있다는 것만 알고 있음

재정의 하는 프로퍼티의 이름과 타입을 모두 명시해야 재정의가 이름과 유형이 동일한 수퍼클래스 프로퍼티와 일치하는지 확인 가능함

상속 받은 프로퍼티 오버라이딩에서

읽기전용 프로퍼티를 getter-setter프로퍼티로 변경해서 제공가능

하지만 getter-setter 프로퍼티를 읽기전용 프로퍼티로는 표시할 수는 없음

만약 setter 를 오버라이드 해서 제공한다면 반드시 getter 도 제공해야함

class Car: Vehicle {
    var gear = 1
    override var description: String {
        return super.description + " in gear \\(gear)"
    }
}

// 계산된 프로퍼티를 오버라이딩 한 예시

let car = Car()
car.currentSpeed = 25.0
car.gear = 3
print("Car: \\(car.description)")
// Car: traveling at 25.0 miles per hour in gear 3

프로퍼티 옵저버 오버라이드

이미 부모클래스에 선언된 프로퍼티 옵저버도 서브클래스에서 재정의해서 사용 가능 함

상수 프로퍼티와 읽기전용 프로퍼티에는 옵저버를 붙일 수 없음.

set을 할 수 없는 프로퍼티이기 때문

또 같은 프로퍼티에 옵저버를 추가하고 setter를 추가해 둘을 동시에 사용할 수 없음

setter를 설정했다면 옵저버를 붙인 것과 같은 동작을 하기 때문!

class AutomaticCar: Car {
    override var currentSpeed: Double {
        didSet {
            gear = Int(currentSpeed / 10.0) + 1
        }
    }
}

let automatic = AutomaticCar()
automatic.currentSpeed = 35.0
print("AutomaticCar: \\(automatic.description)")
// AutomaticCar: traveling at 35.0 miles per hour in gear 4

오버라이드 방지

오버라이드 되는 것을 방지하려면 final 키워드를 사용해서 막을 수 있다.

(final func, final class func, final subscript)