선택적 요구사항의 구현 (Optional Protocol Requirements)
- Swift에서는 프로토콜을 정의할 때, 선택적으로 구현할 수 있는 요구 사항을 선언할 수 있다
- 이를 활용하면 객체가 필요할 때만 특정 기능을 구현하도록 할 수 있다
어트리뷰트 (Attributes)
- Swift에서 어트리뷰트(Attribute) 는 컴파일러에게 특정 정보를 제공하는 키워드이다
- 특정 선언이나 타입에 추가적인 정보 또는 요구 사항을 부여한다
어트리뷰트의 예시
@available: 특정 플랫폼이나 버전에서만 사용 가능하도록 지정한다
@objc: Objective-C와의 호환성을 위해 사용된다
@escaping: 클로저가 함수의 반환 이후에도 사용될 수 있음을 나타낸다
@IBOutlet, @IBAction: Interface Builder와의 연결을 나타낸다
어트리뷰트 사용법
@available(iOS 18.0, *)
class ModernFeature {
func useFeature() {
print("이 기능은 iOS 18.0 이상에서만 사용 가능")
}
}
ModernFeature 클래스는 iOS 18.0 이상에서만 사용 가능하도록 지정되었다
@available 어트리뷰트를 이용하여 특정 버전에만 접근 가능하도록 설정할 수 있다
선택적 요구사항의 구현 (Optional Protocol Requirements)
- Objective-C와의 호환성을 위해 선택적 요구사항을 포함하는 프로토콜을 만들 수 있다
- 이를 위해
@objc와 @objc optional을 사용한다
선택적 요구사항을 포함한 프로토콜 정의하기
@objc protocol MusicPlayer {
@objc optional var volume: Int { get set }
func play()
func stop()
@objc optional func shuffle()
}
@objc를 사용하면 Objective-C와의 호환성을 갖게 된다
@objc optional로 선언된 멤버는 구현해도 되고 하지 않아도 되는 선택적 요구 사항이 된다
MusicPlayer 프로토콜을 채택하는 타입은 shuffle() 메서드를 구현하지 않아도 된다
클래스에서 프로토콜을 채택하고 구현하기
class BasicPlayer: MusicPlayer {
var volume: Int = 5
func play() {
print("음악 재생 중... 볼륨: \(volume)")
}
func stop() {
print("음악 정지")
}
}
class AdvancedPlayer: MusicPlayer {
var volume: Int = 10
func play() {
print("고급 플레이어에서 음악 재생 중... 볼륨: \(volume)")
}
func stop() {
print("고급 플레이어 음악 정지")
}
func shuffle() {
print("곡을 무작위로 섞기")
}
}
BasicPlayer 클래스는 shuffle() 메서드를 구현하지 않았지만 오류 없이 사용 가능하다
AdvancedPlayer 클래스는 shuffle() 메서드를 구현하여 추가 기능을 제공한다
선택적 요구사항의 사용과 타입 확인
- 선택적 요구사항은 프로토콜 타입으로 선언되면 옵셔널 타입으로 인식된다
- 즉, 해당 기능이 구현되지 않았다면
nil을 반환한다
프로토콜 타입으로 저장하기
let basic: MusicPlayer = BasicPlayer()
let advanced: MusicPlayer = AdvancedPlayer()
basic.play()
print(basic.volume ?? 0)
advanced.play()
advanced.shuffle?()
basic은 shuffle() 메서드를 구현하지 않았으므로 호출할 수 없다
advanced는 shuffle() 메서드를 구현했으므로 안전하게 사용할 수 있다
- 선택적 요구사항을 호출할 때는 옵셔널 체이닝 (
?()) 을 사용한다
프로토콜 타입으로 저장할 때의 주의점
print(basic.volume)
print(basic.volume ?? 0)
volume 속성은 선택적 요구사항으로 정의되었기 때문에, basic 객체로 접근하면 옵셔널 타입(Int?)으로 인식된다
- 안전하게 접근하려면 옵셔널 바인딩 또는 기본값을 사용해야 한다
구조체와 열거형은 선택적 요구사항을 구현할 수 없다
- 선택적 요구사항은
@objc를 사용하기 때문에 클래스 전용으로 동작한다
- 구조체와 열거형에서는 프로토콜을 채택할 수 없다
- Swift의 구조체와 열거형은 Objective-C와의 호환성을 제공하지 않기 때문이다
요약
- 선택적 요구사항은
@objc와 @objc optional로 정의할 수 있다
- 선택적 요구사항은 Objective-C의 특징을 활용한 기능으로, Swift의 구조체와 열거형에서는 사용 불가하다
- 선택적 요구사항을 호출할 때는 옵셔널 체이닝을 사용해야 한다 (
?())
- 선택적 요구사항을 포함하는 프로토콜은 클래스 전용 프로토콜로 정의된다