Swift - 상속

임성빈·2022년 3월 27일
0

Swift

목록 보기
13/26
post-thumbnail
post-custom-banner

클래스는 메소드, 프로퍼티와 다른 특징을 다른 클래스로 부터 상속할 수 있다.
이것이 Swift에서 클래스가 다른 타입과 구분되는 근본적인 요소이다. 클래스에서는 저장된 프로퍼티와 계산된 프로퍼티와 상관없이 상속받은 프로퍼티에 프로퍼티 옵저버를 설정해서 값 설정에 반응할 수 있다.


기반 클래스 정의

다른 어떤 클래스로부터도 상속받지 않은 클래스를 기반 클래스라 한다.

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
    }
}

위 코드는 Vehicle 이라는 기반 클래스를 하나 정의한 것이다. 이 VehiclecurrentSpeed 이라는 0.0의 초기값을 갖고 있는 Double 타입의 프로퍼티가 있다. currentSpeed 프로퍼티의 값은 description 이라는 읽기 전용의 계산된 String 타입의 프로퍼티에서 사용되었다. makeNoise() 라는 메소드도 갖고 있다.

Vehicle 클래스를 이용해 someVehicle 이라는 새로운 인스턴스를 만든다.

let someVehicle = Vehicle()

someVehicle 이라는 인스턴스를 통해 Vehicle 클래스 내부의 description 프로퍼티에 접근이 가능하다.

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

서브클래싱

상속, 다시 말해 서브클래싱을 하면 부모로 부터 성격을 상속받고 자기 자신 고유의 특성도 추가할 수 있다.

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

위의 예제를 이용해 설명하자면,

class Bicycle: Vehicle {
    var hasBasket = false
}

BicycleVehicle 을 서브클래싱하고 자기 자신의 속성 hasBasket 도 추가한다.

let bicycle = Bicycle()
bicycle.hasBasket = true

Bicycle 객체를 생성해 고유 속성을 사용할 수 있는 것을 확인할 수 있다.

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

물론 부모로부터 물려받은 속성도 사용 가능하다.

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

class Tandem: Bicycle {
    var currentNumberOfPassengers = 0
}

위 예제를 통해 다시 한 번 모든 설명을 대신한다.


오버라이딩

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


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

super 키워드와 점문법 혹은 인덱스 구문으로 부모 클래스의 메소드, 프로퍼티, 서브스크립트에 접근할 수 있다. super.someMethod , super.someProperty , super[someIndex]

메소드 오버라이드

상속받은 메소드를 오버라이드 하기 위해서는 메소드 선언 앞에 override 키워드를 붙이고 내용을 적으면 된다.

class Train: Vehicle {
    override func makeNoise() {
        print("Choo Choo")
    }
}
let train = Train()
train.makeNoise()
// "Choo Choo" 출력

프로퍼티 오버라이드

서브클래스에서는 상속받은 저장된 프로퍼티, 계산된 프로퍼티 모두 오버라이드 가능하다. 서브클래스에서는 단순히 상속받은 특정 타입의 프로퍼티가 있다는 정도만 알고 있기 때문에 오버라이드시에는 프로퍼티의 이름과 타입을 명시해야한다.

상속받은 읽기 전용 프로퍼티도 getter / setter 를 정의해서 읽고/쓰기가 가능한 프로퍼티로 변경해서 제공 가능하다. 하지만 반대로 읽고/쓰기가 가능한 프로퍼티를 읽기 전용 프로퍼티로 선언하는 것은 할 수 없다.

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

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" 출럭

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

이미 부모클래스에 선언된 프로퍼티 옵저버도 서브클래스에서 재정의해 사용할 수 있다.

다음은 옵저버 오버라이드의 예제이다.
부모의 currentSpeed 계산된 프로퍼티를 오버라이드 했다.

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 로 선언되면 override 되는 것을 막을 수 있다. 만일 final 로 선언된 메소드, 프로퍼티, 서브스크립트를 오버라이드 하려고 하면 컴파일 시간에 에러가 발생한다. 클래스 전체를 final 로 선언해서 클래스 안의 모든 메소드, 프로퍼티 등이 override 가 되는 것을 막을 수 있다.

profile
iOS 앱개발
post-custom-banner

0개의 댓글