Potato
μ•ˆλ…•ν•˜μ„Έμš”, κ°μž‘λ‹ˆλ‹€?πŸ₯” ^___^ 😺 github λ°”λ‘œκ°€κΈ° πŸ‘‰πŸ»

Swift/Swift Documents

[Swift] 곡식 λ¬Έμ„œ 정리 (13) - Inheritance (상속) (Override, final, super, μž¬μ •μ˜, μ˜€λ²„λΌμ΄λ“œ λž€?)

감자 πŸ₯” 2022. 3. 1. 00:26
λ°˜μ‘ν˜•

μ•ˆλ…•ν•˜μ„Έμš”, κ°μžμž…λ‹ˆλ‹€. μ˜€λŠ˜μ€ μŠ€μœ„ν”„νŠΈ 상속(Inheritance)에 λŒ€ν•΄μ„œ κ³΅λΆ€ν–ˆμŠ΅λ‹ˆλ‹€. μ˜€λ²„λΌμ΄λ“œ 라고 정말 μ€‘μš”ν•œ κ°œλ… 쀑 ν•˜λ‚˜μΈλ°μš”, 생각보닀 κ°œλ…μ€ κ°„λ‹¨ν•©λ‹ˆλ‹€. 

Swift Document chap.13 Inheritance λ°”λ‘œκ°€κΈ°


 

Inheritance (상속)

ν΄λž˜μŠ€λŠ” λ‹€λ₯Έ ν΄λž˜μŠ€λ‘œλΆ€ν„° 상속 ν• (받을) 수 μžˆλ‹€. 이것이 ν΄λž˜μŠ€κ°€ λ‹€λ₯Έ νƒ€μž…λ“€κ³Ό κ΅¬λΆ„λ˜λŠ” 근본적인 μš”μ†Œμ΄λ‹€. 단, ν•˜λ‚˜μ˜ 클래슀만 상속 ν•  (받을)수 μžˆλ‹€.

Swift ν΄λž˜μŠ€λŠ” μŠˆνΌν΄λž˜μŠ€μ— μ†ν•œ λ©”μ„œλ“œ, ν”„λ‘œνΌν‹° 및 ν•˜μœ„ 슀크립트λ₯Ό ν˜ΈμΆœν•˜κ³  μ ‘κ·Όν•  수 있으며, ν•΄λ‹Ή λ©”μ„œλ“œ, ν”„λ‘œνΌν‹° 및 슀크립트의 overrideν•œ 버전을 μ œκ³΅ν•˜μ—¬ ν•΄λ‹Ή λ™μž‘μ„ μˆ˜μ •ν•˜κ±°λ‚˜ λ―Έμ„Έ μ‘°μ •ν•  수 μžˆλ‹€.

SwiftλŠ” overrideμ •μ˜μ— μΌμΉ˜ν•˜λŠ” 슈퍼클래슀 μ •μ˜κ°€ μžˆλŠ”μ§€ ν™•μΈν•˜μ—¬ override κ°€ μ˜¬λ°”λ₯Έμ§€ ν™•μΈν•˜λŠ”λ° 도움이 λœλ‹€.

λ˜ν•œ ν΄λž˜μŠ€λŠ” ν”„λ‘œνΌν‹° μ˜΅μ €λ²„λ₯Ό μƒμ†λœ ν”„λ‘œνΌν‹°μ— μΆ”κ°€ν•˜μ—¬ ν”„λ‘œνΌν‹° 값이 변경될 λ•Œ μ•Œλ¦Όμ„ λ°›κ³ , λͺ¨λ‹ˆν„°λ§ ν•  수 μžˆλ‹€. ν”„λ‘œνΌν‹° μ˜΅μ €λ²„λŠ” μ €μž₯/계산 ν”„λ‘œνΌν‹°μ— 상관없이 λͺ¨λ“  ν”„λ‘œνΌν‹°μ— μΆ”κ°€ν•  수 μžˆλ‹€.


 

Defining a Base Class (기본 클래슀)

λ‹€λ₯Έ μ–΄λ–€ ν΄λž˜μŠ€λ‘œλΆ€ν„°λ„ 상속받지 μ•ŠλŠ” 클래슀λ₯Ό “기본클래슀 (base class)” 라고 ν•œλ‹€.

Swift ν΄λž˜μŠ€λŠ” 보편적인 κΈ°λ³Έν΄λž˜μŠ€μ—μ„œ μƒμ†ν•˜μ§€ μ•ŠλŠ”λ‹€. 슈퍼클래슀λ₯Ό μ§€μ •ν•˜μ§€ μ•Šκ³  μ •μ˜ν•˜λŠ” ν΄λž˜μŠ€λŠ” μžλ™μœΌλ‘œ κΈ°λ³Έν΄λž˜μŠ€κ°€ λ˜μ–΄μ„œ extension(ν™•μž₯) ν•  수 μžˆλ‹€.

class Vehicle {

}

μœ„μ˜ Vehicle μ΄λΌλŠ” ν΄λž˜μŠ€λŠ” 아무것도 상속받지 μ•Šκ³  μžˆλ‹€. 이러면 Vehicle은 κΈ°λ³Έ ν΄λž˜μŠ€κ°€ λ˜λŠ” 것이닀.

 

ν”„λ‘œνΌν‹°μ™€ λ©”μ„œλ“œλ₯Ό μΆ”κ°€ν•΄λ³΄μž.

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

let someVehicle = Vehicle()

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

β–· μ½”λ“œμ„€λͺ…

  • Vehicleμ΄λΌλŠ” κΈ°λ³Έ 클래슀λ₯Ό ν•˜λ‚˜ μ •μ˜ν•œ 것
  • currentSpeed ν˜„μž¬μ†λ„λ₯Ό νŒŒλΌλ―Έν„°λ‘œ κ°–κ³ 
  • description 을 μ—°μ‚°ν”„λ‘œνΌν‹°λ₯Ό κ°–μŒ
  • makeNoise() λΌλŠ” λ©”μ„œλ“œ 가짐
  • 이 클래슀λ₯Ό μ΄μš©ν•΄μ„œ vehicle 객체λ₯Ό ν•˜λ‚˜ μƒμ„±ν•˜κ³  discriptionν”„λ‘œνΌν‹°λ₯Ό ν™œμš©ν•˜μ—¬ νƒˆκ²ƒμ˜ ν˜„μž¬ μƒνƒœλ₯Ό 확인

 


 

Subclassing (μ„œλΈŒν΄λž˜μ‹±)

μ„œλΈŒν΄λž˜μ‹±μ„ ν•˜λ©΄ λΆ€λͺ¨λ‘œλΆ€ν„° 성격을 상속받고 μžκΈ°μžμ‹  고유의 νŠΉμ„±λ„ μΆ”κ°€ν•  수 μžˆλ‹€. μ„œλΈŒν΄λž˜μ‹±μ— μƒˆ 클래슀λ₯Ό μ–Έμ–Έν•˜λŠ” μ½”λ“œλŠ” μ•„λž˜μ™€ κ°™λ‹€.

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

μœ„ μ½”λ“œμ—μ„œ SomeSubclassλŠ” μ„œλΈŒν΄λž˜μŠ€μ΄κ³ , : 뒀에 SomeSuperclassλŠ” μŠˆνΌν΄λž˜μŠ€μ΄λ‹€.

 

그럼 μœ„μ—μ„œ Vehicleμ΄λΌλŠ” 클래슀λ₯Ό λ§Œλ“€μ—ˆμœΌλ‹ˆ, 이 Vehicle을 μƒμ†ν•˜λŠ” μ„œλΈŒν΄λž˜μŠ€λ₯Ό ν•˜λ‚˜ λ§Œλ“€μ–΄λ³΄μž.

class Bicycle: Vehicle {
    var hasBasket = false
}
  • Bicycle은 Vehicle 을 μ„œλΈŒν΄λž˜μ‹±ν•˜κ³ , 자기 μžμ‹ μ˜ 속성인 hasBasket을 μΆ”κ°€ν•œλ‹€.
  • 이 Bicycle ν΄λž˜μŠ€λŠ” Vehicle의 ν”„λ‘œνΌν‹°μ™€ λ©”μ„œλ“œλ“€μ„ 상속할 수 μžˆμ„ 뿐만 μ•„λ‹ˆλΌ, μƒˆλ‘œμš΄ νŠΉμ„±κΉŒμ§€λ„ μΆ”κ°€ν•  수 μžˆλ‹€. κ·Έλž˜μ„œ Bicycleν΄λž˜μŠ€λŠ” currentSpeed 및 description속성과 makeNoise() λ©”μ„œλ“œμ™€ 같은 λͺ¨λ“  νŠΉμ„±μ„ μžλ™μœΌλ‘œ μ–»λŠ”λ‹€.
let bicycle = Bicycle()
bicycle.hasBasket = true

Bicycle 객체λ₯Ό μƒμ„±ν•˜μ—¬ 고유 속성을 μ‚¬μš©ν•  수 μžˆλŠ” 것을 확인할 수 μžˆλ‹€.

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

Bicycle 객체λ₯Ό 생성해 고유 속성을 μ‚¬μš©ν•  수 μžˆλŠ” 것을 확인할 수 μžˆλ‹€.

 

μ„œλΈŒν΄λž˜μŠ€λ‘œ μƒμ„±λœ 클래슀λ₯Ό λ‹€μ‹œ μ„œλΈŒν΄λž˜μ‹±ν•˜λŠ” 것도 κ°€λŠ₯ν•˜λ‹€.

class Tandem: Bicycle {
    var currentNumberOfPassengers = 0
}

Bicycle을 μ„œλΈŒν΄λž˜μ‹±ν•΄μ„œ Tandemμ΄λΌλŠ” 클래슀λ₯Ό μƒμ„±ν•˜κ³  속성도 μΆ”κ°€ν•΄λ³΄μž.

let tandem = Tandem()
tandem.hasBasket = true
tandem.currentNumberOfPassengers = 2
tandem.currentSpeed = 22.0
print("Tandem: \\(tandem.description)")
// Tandem: traveling at 22.0 miles per hour

Tandem은 Tandem 객체 고유 속성인 currentNumberOfPassengers 와 μžμ‹ μ˜ λΆ€λͺ¨ Bicycle의 속성, 그리고 μ‘°λΆ€λͺ¨μΈ Vehicle의 속성도 λͺ¨λ‘ μžλ™μœΌλ‘œ μ–»λŠ”λ‹€.


 

Overriding (μ˜€λ²„λΌμ΄λ”©, μž¬μ •μ˜)

μ„œλΈŒν΄λž˜μŠ€μ—μ„œλŠ” λΆ€λͺ¨ν΄λž˜μŠ€μ—μ„œ 상속받은 것을 μž¬μ •μ˜ν•  수 μžˆλ‹€. μ˜€λ²„λΌμ΄λ”©μ€ μΈμŠ€ν„΄μŠ€ λ©”μ„œλ“œ, νƒ€μž… λ©”μ„œλ“œ, μΈμŠ€ν„΄μŠ€ ν”„λ‘œνΌν‹°, νƒ€μž… ν”„λ‘œνΌν‹°, 슀크립트 λͺ¨λ‘μ— λŒ€ν•΄ κ°€λŠ₯ν•˜λ‹€.

μ˜€λ²„λΌμ΄λ“œλ₯Ό μœ„ν•΄μ„œλŠ” μ„ μ–Έ μ•žμ— override ν‚€μ›Œλ“œλ₯Ό μž‘μ„±ν•΄μ£Όλ©΄ λœλ‹€. Swiftμ—μ„œλŠ” override ν‚€μ›Œλ“œλ₯Ό 보면 μž¬μ •μ˜λ₯Ό μœ„ν•΄ μ œκ³΅ν•œ 것과 μΌμΉ˜ν•˜λŠ” 선언을 슈퍼클래슀, 슈퍼클래슀의 슈퍼클래슀 등에 μ„ μ–Έν–ˆλŠ”μ§€ ν™•μΈν•˜λ„λ‘ μš”μ²­ν•œλ‹€. 이 κ²€μ‚¬λŠ” override μ •μ˜κ°€ μ˜¬λ°”λ₯Έμ§€ ν™•μΈν•œλ‹€.

Accessing Superclass Methods, Properties and Subscripts

super ν‚€μ›Œλ“œμ™€ 점문법 ν˜Ήμ€ 인덱슀 ꡬ문으둜 λΆ€λͺ¨ν΄λž˜μŠ€μ˜ λ©”μ„œλ“œ, ν”„λ‘œνΌν‹°, μ„œλΈŒν΄λž˜μŠ€μ— μ ‘κ·Όν•  수 μžˆλ‹€.

Overriding Methods (λ©”μ„œλ“œ μ˜€λ²„λΌμ΄λ”©)

  • μ˜€λ²„λΌμ΄λ”© λŒ€μƒμ΄ λ˜λŠ” λ©”μ„œλ“œμ˜ λ§€κ°œλ³€μˆ˜ κ°œμˆ˜λ‚˜ νƒ€μž…, 그리고 λ°˜ν™˜νƒ€μž…μ€ λ³€κ²½ν•  수 μ—†λ‹€.
  • λ©”μ„œλ“œ μ˜€λ²„λΌμ΄λ”©μ„ 톡해 λ³€κ²½ν•  수 μžˆλŠ” 것은 μ˜€λ‘œμ§€ λ‚΄λΆ€ ꡬ문 뿐이닀.

μ•„λž˜ μ½”λ“œλŠ” κΈ°μ‘΄ Vehicle 클래슀λ₯Ό 상속받아 λ§Œλ“€μ–΄μ§„ Train ν΄λž˜μŠ€μ΄λ‹€. λΆ€λͺ¨ 클래슀의 κΈ°μ‘΄ λ©”μ„œλ“œμΈ makeNoise() λ©”μ„œλ“œλ₯Ό overrideν–ˆλ‹€.

overrideλŠ” λ‹€μ‹œ μ •μ˜ν•˜λŠ” 것이기 λ•Œλ¬Έμ— 이름이 무쑰건 κ°™μ•„μ•Όν•œλ‹€. 그리고 override ν‚€μ›Œλ“œλ₯Ό 뢙이면 λœλ‹€.

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

let train = Train()
train.makeNoise()
// Prints "Choo Choo" : μƒˆλ‘œ μ •μ˜ν•œ λ‚΄μš©μ΄ 좜λ ₯λ©λ‹ˆλ‹€.

μ΄λ ‡κ²Œ ν•˜κ²Œ 되면 κΈ°μ‘΄ λ©”μ„œλ“œλŠ” μ•„λž˜μ²˜λŸΌ μ‚¬μš© κ°€λŠ₯ν•˜λ‹€. (super ν‚€μ›Œλ“œ)

class Train: Vehicle {
    override func makeNoise() {
        super.makeNoise()
    }
}

 

Overriding Properties (ν”„λ‘œνΌν‹° μ˜€λ²„λΌμ΄λ”©)

  • μ €μž₯ ν”„λ‘œνΌν‹°, μ—°μ‚° ν”„λ‘œνΌν‹° λͺ¨λ‘ μ˜€λ²„λΌμ΄λ“œ κ°€λŠ₯
  • μ €μž₯ ν”„λ‘œνΌν‹°λ₯Ό μ˜€λ²„λΌμ΄λ”© ν•  λ•ŒλŠ” 계산 ν”„λ‘œνΌν‹°κ°€ λœλ‹€. (상속받은 μ½κΈ°μ „μš© ν”„λ‘œνΌν‹°λ„ 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

좜λ ₯을 해보면, μž¬μ •μ˜ 된 μƒνƒœλ‘œ 좜λ ₯λ˜λŠ” 것을 확인할 수 μžˆλ‹€.

 

Overriding Property Observers (ν”„λ‘œνΌν‹° μ˜΅μ €λ²„ μ˜€λ²„λΌμ΄λ”©)

  • ν”„λ‘œνΌν‹° μ˜€λ²„λΌμ΄λ”©μ„ ν™œμš©ν•˜μ—¬ μƒμ†λœ ν”„λ‘œνΌν‹°μ— ν”„λ‘œνΌν‹° μ˜΅μ €λ²„λ₯Ό μΆ”κ°€ν•  수 있음.
  • μƒμ†λœ ν”„λ‘œνΌν‹°μ˜ 값이 변경될 λ•Œ, ν•΄λ‹Ή ν”„λ‘œνΌν‹°κ°€ 처음 κ΅¬ν˜„λœ 것과 상관 없이 μ•Œλ¦Όμ„ 받을 수 μžˆλ‹€.
  • μƒμ†λœ μƒμˆ˜ μ €μž₯ ν”„λ‘œνΌν‹° λ˜λŠ” μ½κΈ°μ „μš© 계산 ν”„λ‘œνΌν‹°μ—λŠ” ν”„λ‘œνΌν‹° μ˜΅μ €λ²„λ₯Ό μΆ”κ°€ν•  수 μ—†λ‹€.
  • λ™μΌν•œ ν”„λ‘œνΌν‹°μ— λŒ€ν•΄ override setter와 override ν”„λ‘œνΌν‹° μ˜΅μ €λ²„λ₯Ό λ‘˜ λ‹€ μ œκ³΅ν•  μˆ˜λŠ” μ—†λ‹€.

 

μ˜΅μ €λ²„ μ˜€λ²„λΌμ΄λ”© 예제 μ½”λ“œλ₯Ό μ‚΄νŽ΄λ³΄μž.

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

currentSpeed 계산 ν”„λ‘œνΌν‹°λ₯Ό μ˜€λ²„λΌμ΄λ“œ ν–ˆλ‹€.

μ½”λ“œ μ‹€ν–‰κ²°κ³Ό μ˜€λ²„λΌμ΄λ“œ ν•œ λ‚΄μš©μ΄ 좜λ ₯λ˜λŠ” 것을 λ³Ό 수 μžˆλ‹€.


 

Preventing Overrides (μ˜€λ²„λΌμ΄λ”© λ°©μ§€ν•˜κΈ° final)

  • μ˜€λ²„λΌμ΄λ“œλ₯Ό μ›μΉ˜ μ•Šμ„ 경우 μ‚¬μš©ν•œλ‹€.
    (μ„œλΈŒν΄λž˜μŠ€μ—μ„œ νŠΉμ • λ©”μ„œλ“œ, ν”„λ‘œνΌν‹°, μ„œλΈŒμŠ€ν¬λ¦½νŠΈκ°€ μ˜€λ²„λΌμ΄λ“œ λ˜λŠ” 것을 λ°©μ§€ν•˜κΈ° μœ„ν•΄ μ‚¬μš©)
  • final ν‚€μ›Œλ“œλ₯Ό 뢙인닀.
  • 클래슀 전체λ₯Ό final둜 μ„ μ–Έν•΄μ„œ 클래슀 μ•ˆμ˜ λͺ¨λ“  λ©”μ„œλ“œ, ν”„λ‘œνΌν‹° 등이 override λ˜λŠ” 것을 막을 수 μžˆλ‹€.
λ°˜μ‘ν˜•