TIL: 지정 생성자 / 편의 생성자 상속과 재정의 규칙

Royce·2025년 3월 23일

Swift 문법

목록 보기
35/63

생성자의 상속과 재정의 (기본 원칙)

상위 클래스의 생성자가 하위 클래스에서 상속되지 않는 이유

  • 하위 클래스는 상위 클래스의 생성자를 기본적으로 상속하지 않는다
  • 하위 클래스에 정의된 저장 속성이 초기화되지 않을 위험을 방지하기 위해서이다
  • 하위 클래스는 자신의 저장 속성을 완전히 초기화하기 전에 상위 클래스의 초기화를 호출해야 한다 (super.init())

상위 클래스의 생성자를 하위 클래스에서 사용하려면 재정의가 필요하다 (Override)

  • 상위 클래스의 지정 생성자를 하위 클래스에서 동일한 이름으로 구현하려면 override 키워드를 사용해야 한다
  • 상위 클래스의 지정 생성자를 하위 클래스에서 편의 생성자로 재정의하는 것도 가능하다 (override convenience)

편의 생성자의 자동 상속 조건

  1. 하위 클래스에서 모든 저장 속성이 기본값으로 초기화되면, 상위 클래스의 지정 생성자가 자동으로 상속된다
  2. 하위 클래스에서 상위 클래스의 모든 지정 생성자를 재정의하면, 상위 클래스의 편의 생성자가 자동으로 상속된다

지정 생성자와 편의 생성자의 상속과 재정의 예제

// 📌 기본(Base) 클래스 정의
class Appliance {
    var brand: String  // 저장 속성 (필수 초기화 대상)
    
    // 지정 생성자 (Designated Initializer)
    init(brand: String) {
        self.brand = brand  // 저장 속성 초기화
    }
    
    // 편의 생성자 (Convenience Initializer)
    convenience init() {
        self.init(brand: "Unknown")  // 지정 생성자를 호출하여 초기화 (Delegate Across)
    }
}

// 📝 Appliance 클래스 테스트
let appliance1 = Appliance()
let appliance2 = Appliance(brand: "Samsung")
print("Appliance1 Brand: \(appliance1.brand)")  // 출력: Appliance1 Brand: Unknown
print("Appliance2 Brand: \(appliance2.brand)")  // 출력: Appliance2 Brand: Samsung

// 📌 하위 클래스 정의 (상속)
class WashingMachine: Appliance {
    var capacity: Int  // 새로운 저장 속성 추가
    
    // 지정 생성자 (상위의 init(brand:)와 동일한 이름으로 구현 - 재정의 필요)
    override init(brand: String) {
        self.capacity = 0  // 새로운 저장 속성 초기화
        super.init(brand: brand)  // 상위 클래스의 지정 생성자 호출 (Delegate Up)
    }
    
    // 지정 생성자 (하위 클래스에서 새로운 지정 생성자 추가)
    init(brand: String, capacity: Int) {
        self.capacity = capacity  // 새로운 저장 속성 초기화
        super.init(brand: brand)  // 상위 클래스의 지정 생성자 호출 (Delegate Up)
    }
    
    // 편의 생성자 (Delegate Across)
    convenience init() {
        self.init(brand: "LG", capacity: 8)  // 동일 클래스의 다른 지정 생성자를 호출하여 초기화
    }
}

// 📝 WashingMachine 클래스 테스트
let washer1 = WashingMachine()
let washer2 = WashingMachine(brand: "Whirlpool")
let washer3 = WashingMachine(brand: "Bosch", capacity: 12)

print("Washer1: \(washer1.brand), Capacity: \(washer1.capacity)")  // 출력: Washer1: LG, Capacity: 8
print("Washer2: \(washer2.brand), Capacity: \(washer2.capacity)")  // 출력: Washer2: Whirlpool, Capacity: 0
print("Washer3: \(washer3.brand), Capacity: \(washer3.capacity)")  // 출력: Washer3: Bosch, Capacity: 12

Apple 공식 문서의 예제

class Vehicle {
    var numberOfWheels = 0  // 저장 속성 (기본값 제공)
    
    var description: String {
        return "\(numberOfWheels) wheel(s)"
    }
}

// 📝 Vehicle 클래스 테스트
let vehicle = Vehicle()
print("Vehicle: \(vehicle.description)")  // 출력: Vehicle: 0 wheel(s)


class Bicycle: Vehicle {
    
    // 지정 생성자 (상위 지정 생성자와 동일한 이름으로 재정의)
    override init() {
        super.init()  // 상위 클래스의 지정 생성자 호출
        numberOfWheels = 2  // 2단계 초기화 (값 설정)
    }
}

let bicycle = Bicycle()
print("Bicycle: \(bicycle.description)")  // 출력: Bicycle: 2 wheel(s)


class Hoverboard: Vehicle {
    var color: String  // 새로 추가된 저장 속성
    
    init(color: String) {
        self.color = color  // 새로운 저장 속성 초기화
        super.init()  // 상위 클래스의 지정 생성자 호출 (암시적 호출 가능)
    }
    
    override var description: String {  // description 속성 재정의
        return "\(super.description) in a beautiful \(color)"
    }
}

let hoverboard = Hoverboard(color: "Silver")
print("Hoverboard: \(hoverboard.description)")  // 출력: Hoverboard: 0 wheel(s) in a beautiful Silver

요약

  • 지정 생성자는 모든 저장 속성을 초기화하고 상위 클래스의 지정 생성자를 호출해야 한다 (super.init())
  • 편의 생성자는 동일 클래스의 지정 생성자를 호출하여 초기화를 위임한다 (self.init())
  • 지정 생성자는 편의 생성자를 호출할 수 없다
  • 편의 생성자는 상위 클래스의 지정 생성자를 직접 호출할 수 없다
  • 지정 생성자를 재정의하려면 override 키워드를 사용해야 한다
  • 하위 클래스에서 모든 저장 속성을 기본값으로 초기화하면, 상위 클래스의 지정 생성자가 자동으로 상속된다
  • 상위 클래스의 모든 지정 생성자를 재정의하면, 상위 클래스의 편의 생성자가 자동으로 상속된다
profile
iOS 개발자 지망생

0개의 댓글