클래스는 메서드
, 프로퍼티
및 다른 특성
을 다른 클래스에서 상속할 수 있습니다. 한 클래스가 다른 클래스에서 상속되는 경우 상속을 받는 클래스는 서브 클래스
, 상속을 하는 클래스는 슈퍼클래스
입니다. 상속은 Swift의 다른 타입들과 클래스를 차별화하는 핵심적인 기능입니다.
Swift의 클래스는 해당 슈퍼클래스에 속하는 메서드
, 프로퍼티
및 서브스크립트
를 호출하고 액세스할 수 있으며 이러한 메서드, 프로퍼티 및 서브스크립트의 동작을 세분화하거나 수정할 수 있는 자체 재정의(overriding) 버전
을 제공할 수 있습니다. Swift는 재정의 정의에 일치하는 슈퍼클래스 정의가 있는지 확인하여 재정의가 올바른지 확인하는 데 도움이 됩니다.
클래스는 프로퍼티 값이 변경될 때 알림을 받기 위해 상속된 프로퍼티에 프로퍼티 옵저버
를 추가할 수도 있습니다. 프로퍼티 옵저버
는 원래 stored property
로 정의되었는지 또는 computed property
으로 정의되었는지에 관계없이 모든 속성에 추가할 수 있습니다.
다른 클래스에서 상속되지 않는 클래스를 기본 클래스(Base Class)
라고 합니다.
스위프트 클래스는 범용 기본 클래스(Universal base class)에서 상속되지 않습니다.
슈퍼 클래스를 지정하지 않고 정의한 클래스는 자동으로 빌드할 기본 클래스가 됩니다.
아래의 예는 Vehicle
이라는 기본 클래스를 정의합니다. 이 기본 클래스는 기본값이 0.0(프로퍼티 타입은 Double로 추론)인currentSpeed
라는 저장 프로퍼티를 정의합니다. currentSpeed
프로퍼티 값은 description
이라는 read-only 연산 String 프로퍼티
에서vehicle
에 대한 description
을 만드는 데 사용됩니다.
Vehicle
기본 클래스는 makeNoise
라는 메서드도 정의합니다. 이 메서드는 기본 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
}
}
Initializer 구문을 사용하여 Vehicle
의 새 인스턴스를 만듭니다. 이 인스턴스는 타입이름(Vehicle)과 빈 괄호()로 작성됩니다.
let someVehicle = Vehicle()
새 Vehicle
인스턴스를 만든 후에는, description
프로퍼티에 액세스하여 사람이 읽을 수 있는 차량 현재 속도에 대한 description
을 출력할 수 있습니다.
print("Vehicle: \(someVehicle.description)")
// Vehicle: Traveling at 0.0 miles per hour
Vehicle
클래스는 임의의 차량에 대한 일반적인 특성을 정의하지만 그 자체로는 그다지 유용하지 않습니다. 이 클래스를 더 유용하게 만들기 위해서는, 더 구체적인 종류의 차량을 표현할 수 있도록 다듬어야 합니다.
Subclassing
은 기존 클래스를 기반으로 새 클래스를 만드는 작업입니다. 서브클래스는 기존 클래스의 특성을 상속하며, 이 특성을 세분화할 수 있습니다. 서브클래스에 새 특성을 추가할 수도 있습니다.
서브 클래스에 superclass가 있음을 나타내려면 superclass 이름 앞에 subclass 이름을 콜론으로 구분하여 기록합니다.
class SomeSubclass: SomeSuperclass {
// subclass definition goes here
}
다음은 Vehicle
이라는 슈퍼클래스가 있는, Bicycle
이라는 서브클래스를 정의하는 예입니다.
class Bicycle: Vehicle {
var hasBasket = false
}
새로운 Bicycle
클래스는 currentSpeed
및 description
과 makeNoise()
메소드 등 Vehicle
의 모든 특성을 자동으로 획득합니다.
Bicycle
클래스는 상속되는 특성 외에도 새 저장 프로퍼티를 정의하며 기본값이 false(프로퍼티 타입 유추(Bool))인 hasBasket
를 가집니다.
기본적으로 새로 만드는 모든 Bicycle
인스턴스에는 basket
이 없습니다.
특정 Bicycle
인스턴스가 생성된 후 hasBasket
속성을 true로 설정할 수 있습니다.
let bicycle = Bicycle()
bicycle.hasBasket = true
Bicycle
인스턴스의 상속된 currentSpeed
프로퍼티를 수정하고 인스턴스의 상속된 description
프로퍼티를 쿼리할 수도 있습니다.
bicycle.currentSpeed = 15.0
print("Bicycle: \(bicycle.description)")
// Bicycle: traveling at 15.0 miles per hour
서브클래스 자체가 서브클래스가 될 수 있습니다. 다음 예에서는 "tandem" 으로 알려진 2인승 Bicycle
의 서브클래스를 만듭니다.
class Tandem: Bicycle {
var currentNumberOfPassengers = 0
}
Tandem
은 Bicycle
로부터 모든 프로퍼티 및 메소드를 상속받는데, 이는 Vehicle
으로부터 상속받은 모든 프로퍼티 및 메소드입니다.
또한 Tandem
서브클래스는 기본값이 0인 currentNumberOfPassengers
라는 새 저장 프로퍼티를 추가합니다.
Tandem
인스턴스를 만드는 경우, Tandem의 새 프로퍼티와 상속된 프로퍼티로 작업하고 Vehicle
에서 상속되는 read-only description
설명 속성을 쿼리할 수 있습니다.
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
서브클래스
는 인스턴스 메서드, 타입 메서드, 인스턴스 프로퍼티, 타입 프로퍼티 또는 슈퍼클래스로부터 상속되는 서브스크립트의 사용자 지정 구현을 제공할 수 있습니다. 이것을 재정의(오버라이드)라고 합니다.
상속될 특성을 재정의하려면 재정의 정의에 override
키워드 접두사를 지정합니다. 이렇게 하면 오버라이드 할 의도이며 실수로 일치하는 정의를 제공하지 않았음을 알 수 있습니다. 실수로 재정의하면 예기치 않은 동작이 발생할 수 있으며 override
키워드가 없는 재정의는 코드를 컴파일할 때 오류로 진단됩니다.
override
키워드는 또한 Swift 컴파일러에게 오버라이딩 클래스의 슈퍼클래스(또는 상위 클래스 중 하나)에 오버라이드 선언과 일치하는 선언이 있는지 확인하라는 메시지를 표시합니다. 이 검사는 오버라이드 정의가 올바른지 확인합니다.
서브클래스에 대한 메서드, 프로퍼티 또는 서브스크립트 오버라이드를 제공할 때 기존 슈퍼클래스 구현을 오버라이드의 일부로 사용하는 것이 유용한 경우가 있습니다. 예를 들어 기존 구현의 동작을 세분화하거나 수정된 값을 기존 상속 변수에 저장할 수 있습니다.
적절한 경우 super
접두사를 사용하여 메서드, 프로퍼티 또는 서브스크립트의 superclass
버전에 접근합니다.
someMethod()
라는 오버라이드 메서드는 오버라이드 메서드 구현 내에서 super.someMethod()
를 호출하여 someMethod()
의 슈퍼클래스 버전을 호출할 수 있습니다.someProperty
라는 오버라이드된 속성은 someProperty
의 superclass
버전에 오버라이딩 된 getter 또는 setter 구현이 포함된super.someProperty
로 액세스할 수 있습니다.someIndex
라는 오버라이드된 서브스크립트는 super[someIndex]
과(와) 동일한, [someIndex]를 재정의하는 서브스크립트 구현 내에서 가져온 서브스크립트의 superclass 버전에 액세스할 수 있습니다.상속된 인스턴스 또는 타입 메서드를 재정의하여 서브클래스 내에서 메서드의 맞춤형 또는 대체 구현을 제공할 수 있습니다.
다음 예제는 Train
이 Vehicle
에서 상속하는 makeNoise()
메소드를 재정의하는 Train
이라는 새로운 Vehicle
의 서브클래스를 정의합니다.
class Train: Vehicle {
override func makeNoise() {
print("Choo Choo")
}
}
새로운 Train
인스턴스를 만들고 makeNoise()
메서드를 호출하면 Train
서브클래스 버전의 메서드를 다음과 같이 호출할 수 있습니다.
let train = Train()
train.makeNoise()
// Prints "Choo Choo"
상속된 인스턴스 또는 타입 프로퍼티를 재정의하여 해당 프로퍼티에 대한 사용자 지정 getter
및 setter
를 제공하거나, 오버라이딩 프로퍼티가 기본 속성 값이 변경될 때 관찰할 수 있도록 프로퍼티 옵저버
를 추가할 수 있습니다.
상속된 프로퍼티가 저장 프로퍼티
으로 구현되는지 또는 연산 프로퍼티
로 구현되는지에 대한 여부와 관계없이, 상속된 프로퍼티를 재정의하는 사용자 지정 getter(및 적절한 경우)
를 제공할 수 있습니다. 상속된 저장 또는 연산 프로퍼티는 서브클래스
에서 알 수 없습니다. 상속된 프로퍼티의 이름과 타입이 특정하다는 것만 알 수 있습니다. 재정의할 프로퍼티의 이름과 타입을 항상 명시해야 컴파일러에서 재정의할 이름과 타입이 동일한 슈퍼클래스 속성과 일치하는지 확인할 수 있습니다.
서브클래스 프로퍼티 재정의에서 getter
와 setter
를 모두 제공하여 상속된 read-only property
를 read-write property
으로 나타낼 수 있습니다. 그러나 상속된 read-write property
는 read-only property
로 제공할 수 없습니다.
NOTE
프로퍼티 재정의의 일부로 setter를 제공하는 경우 해당 재정의에 대한 getter도 제공해야 합니다. 재정의한 getter로 상속된 프로퍼티 값을 수정하지 않으려면 getter에super.someProperty
를 반환하여 상속된 값을 통과하면 됩니다. 여기서 someProperty는 재정의할 속성의 이름입니다.
다음 예에서는 Car
이라는 새로운 클래스를 정의합니다. 이 클래스는 Vehicle
의 슈퍼클래스입니다. Car
클래스는 기본 정수 값이 1인 gear
라는 새 저장 프로퍼티를 구현합니다. 또한 car
클래스는 Vehicle
으로부터 상속되는 description
프로퍼티를 오버라이드하여 현재 gear
가 포함된 사용자 지정 description
을 제공합니다.
class Car: Vehicle {
var gear = 1
override var description: String {
return super.description + " in gear \(gear)"
}
}
description
프로퍼티의 재정의는 super.description
을 호출하는 것으로 시작되며, 이 경우 Vehicle
클래스의 description
프로퍼티가 반환됩니다. 그런 다음 Car
클래스의 description
버전은 이 description
끝에 현재 gear
에 대한 정보를 제공하기 위해 텍스트를 추가합니다.
Car 클래스의 인스턴스를 만들고 해당 gear
및 currentSpeed
프로퍼티을 설정하면 해당 description property
가 Car 클래스에 정의된 맞춤형 설명을 반환하는 것을 볼 수 있습니다.
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
프로퍼티 오버라이딩을 사용하여 상속된 프로퍼티에 프로퍼티 옵저버
를 추가할 수 있습니다. 이렇게 하면 해당 프로퍼티가 처음 구현된 방식에 관계없이 상속된 프로퍼티의 값이 변경될 때 알림을 받을 수 있습니다. 프로퍼티 옵저버
에 대한 자세한 내용은 Property Observers를 참조하십시오.
NOTE
상속된상수 저장 프로퍼티
또는 상속된read-only 연산 프로퍼티
에 프로퍼티 옵저버를 추가할 수 없습니다. 이러한 프로퍼티 값은 설정할 수 없으므로 오버라이드의 일부로willSet
또는didSet
구현을 제공하는 것은 적절하지 않습니다.
또한 동일한 프로퍼티에 대해오버라이딩 setter
와오버라이딩 프로퍼티 옵저버
를 모두 제공할 수 없습니다. 프로퍼티의 값 변경을 관찰하려는 경우, 해당 프로퍼티에 대한사용자 지정 setter
를 이미 제공 중인 경우사용자 지정 setter
내에서 모든 값 변경을 관찰할 수 있습니다.
다음 예제에서는 AutomaticCar
라는 새로운 클래스를 정의합니다. 이 클래스는 Car
의 서브클래스입니다. AutomaticCar
클래스는 자동 변속 장치가 장착된 Car
을 나타내며, 자동 변속 장치는 현재 속도에 따라 적합한 기어를 자동으로 선택합니다.
class AutomaticCar: Car {
override var currentSpeed: Double {
didSet {
gear = Int(currentSpeed / 10.0) + 1
}
}
}
AutomaticCar
인스턴스의 currentSpeed
프로퍼티를 설정할 때마다 프로퍼티의 didSet 옵저버
가 인스턴스의 gear
프로퍼티를 새 속도에 적합한 기어 선택으로 설정합니다. 특히, 프로퍼티 옵저버는 새로운 currentSpeed
값을 10으로 나누고 가장 가까운 정수로 반올림하여 1을 더한 기어를 선택합니다. 35.0의 속도는 4의 기어를 생성합니다.
let automatic = AutomaticCar()
automatic.currentSpeed = 35.0
print("AutomaticCar: \(automatic.description)")
// AutomaticCar: traveling at 35.0 miles per hour in gear 4
메서드
, 프로퍼티
또는 서브스크립트
를 final
로 표시하여 오버라이드
하지 못하도록 할 수 있습니다. 메서드, 프로퍼티 또는 서브스크립트의 introducer 키워드
앞에 final
modifier 를 작성하여 이 작업을 수행합니다.(예: final var, final func, final class func 및 final subscript)
서브클래스의 final
메서드, 프로퍼티 또는 서브스크립트를 오버라이드 하려고 하면 컴파일 타임 에러로 보고됩니다. 확장(extension)
에서 클래스에 추가하는 메서드, 프로퍼티 또는 서브스크립트도 확장 정의 내에서 final
으로 표시할 수 있습니다.
클래스 정의에서 class
키워드 앞에 final
을 작성하여 전체 클래스를 final
으로 표시할 수 있습니다(final class
). final
클래스를 서브클래스 하려는 시도는 컴파일 타임 에러로 보고됩니다.