프로토콜(Protocols)
- 어떤 기능에 필요한 요구사항을 선언해두는 것
- 클래스, 구조체, 열거형에 의해 채택
프로토콜 문법
protocol SomeProtocol {
// protocol definition
}
프로토콜을 따르는 타입을 정의하기 위해서는 타입 이름 뒤에 콜론(:)을 붙이고 프로토콜 이름을 적음
프로토콜을 채택할 때는 프로토콜에 정의된 요구사항을 반드시 구현 해야만 함
struct SomeStructure: FirstProtocol, AnotherProtocol {
// structure definition goes here
}
class SomeClass: SomeSuperclass, FirstProtocol, AnotherProtocol {
// class definition goes here
}
프로토콜 요구사항 정의
프로퍼티 요구사항
- 프로퍼티의 이름과 타입 그리고 gettable, settable 한지 명시해야 함
- 연산 프로퍼티는 항상 var로 선언해야함(저장 프로퍼티는 gettable 만 가능한 경우에는 let으로 선언 가능), 타입 프로퍼티는 static 키워드 사용
protocol SomeProtocol {
var mustBeSettable: Int { get set }
var doesNotNeedToBeSettable: Int { get }
static var someTypeProperty: Int { get set }
}
메소드 요구사항
- 필수 인스턴스 메소드와 타입 메소드 명시 가능
- 메소드 파라미터의 기본값은 사용 불가
protocol SomeProtocol {
static func someTypeMethod()
func random() -> Double
}
변경 가능한 메소드 요구사항
- mutating 키워드를 사용해 인스턴스에서 변경 가능하다는 것을 표시
- mutating 키워드는 값 타입에서만 사용
protocol Togglable {
mutating func toggle()
}
초기자 요구사항
- 프로토콜에서 필수로 구현해야하는 이니셜라이저 지정 가능
- 구현할 때 이니셜라이저 앞에 required 키워드를 붙여줘야함
protocol SomeProtocol {
init(someParameter: Int)
}
class SomeClass: SomeProtocol {
required init(someParameter: Int) {
// initializer implementation goes here
}
}
- 프로토콜을 채택하고 클래스를 상속받는 경우 이니셜라이저 앞에 required 키워드와 override 키워드를 적어야함
protocol SomeProtocol {
init()
}
class SomeSuperClass {
init() {
// initializer implementation goes here
}
}
class SomeSubClass: SomeSuperClass, SomeProtocol {
// "required" from SomeProtocol conformance; "override" from SomeSuperClass
required override init() {
// initializer implementation goes here
}
}
타입으로써의 프로토콜
프로토콜도 타입으로 사용가능
- 함수, 메소드, 이니셜라이저의 파라미터 타입 혹은 리턴 타입
- 상수, 변수, 프로퍼티의 타입
- 컨테이너인 배열, 사전 등의 아이템 타입
프로토콜 위임
클래스 혹은 구조체 인스턴스에 특정 행위에 대한 책임을 넘길 수 있게 해주는 디자인 패턴
익스텐션의 사용
- 이미 존재하는 타입에 새 프로토콜을 따르게 하기위해 익스텐션을 사용
- 원래 값에 접근 권한이 없어도 익스텐션을 사용해 기능 확장 가능
protocol TextRepresentable {
var textualDescription: String { get }
}
조건적으로 프로토콜 따르기
where 키워드를 사용해 특정 조건을 만족시킬 때만 프로토콜을 따르도록 제한
프로토콜 타입 컬렉션
프로토콜을 collection 타입에 넣기위한 타입으로 사용가능
let things: [TextRepresentable] = [game, d12, simonTheHamster]
for thing in things {
print(thing.textualDescription)
}
// A game of Snakes and Ladders with 25 squares
// A 12-sided dice
// A hamster named Simon
프로토콜 상속
클래스 상속같이 프로토콜도 상속 가능, 콤마(,)로 구분
protocol InheritingProtocol: SomeProtocol, AnotherProtocol {
// protocol definition goes here
}
클래스 전용 프로토콜
프로토콜에 AnyObject를 추가
protocol SomeClassOnlyProtocol: AnyObject, SomeInheritedProtocol {
// class-only protocol definition goes here
}
프로토콜 합성
동시에 여러 프로토콜을 따르는 타입을 선언 가능
protocol Named {
var name: String { get }
}
protocol Aged {
var age: Int { get }
}
struct Person: Named, Aged {
var name: String
var age: Int
}
func wishHappyBirthday(to celebrator: Named & Aged) {
print("Happy birthday, \\(celebrator.name), you're \\(celebrator.age)!")
}
let birthdayPerson = Person(name: "Malcolm", age: 21)
wishHappyBirthday(to: birthdayPerson)
// Prints "Happy birthday, Malcolm, you're 21!"
프로토콜 순응 확인
어떤 타입이 특정 프로토콜을 따르는지 다음과 같은 방법으로 확인 가능
- is연산자를 이용하면 어떤 타입이 특정 프로토콜을 따르는지 확인가능
- 특정 프로토콜을 따르면 true를 아니면 false를 반환합니다.
- as?는 특정 프로토콜 타입을 따르는 경우 그 옵셔널 타입의 프로토콜 타입으로 다운캐스트를 하게 되고 따르지 않는 경우는 nil을 반환
- as!는 강제로 특정 프로토콜을 따르도록 정의
- 만약 다운캐스트에 실패하면 런타임 에러가 발생
선택적 프로토콜 요구조건
- 선택적 구현 조건을 정의 가능
- @objc 키워드를 프로토콜 앞에 붙이고 개별 함수 혹은 프로퍼티에는 @objc 와 optional 키워드 사용
- @objc 프로토콜은 클래스 타입에서만 사용될 수 있고 구조체나 열거형에서는 사용할 수 없음
@objc protocol CounterDataSource {
@objc optional func increment(forCount count: Int) -> Int
@objc optional var fixedIncrement: Int { get }
}
프로토콜 익스텐션
익스텐션을 사용해 프로토콜 확장가능
기본 구현 제공
- 익스텐션을 기본 구현을 제공하는데 사용 가능
- 프로토콜에서는 선언만 할 수 있는데 익스텐션을 이용해 기본 구현을 제공
extension PrettyTextRepresentable {
var prettyTextualDescription: String {
return textualDescription
}
}
프로토콜 익스텐션에 제약 추가
- 익스텐션이 특정 조건에서만 적용되도록 where 절을 사용해 선언 가능
extension Collection where Element: Equatable {
func allEqual() -> Bool {
for element in self {
if element != self.first {
return false
}
}
return true
}
}
반응형
'⌨️ Language > swift' 카테고리의 다른 글
[Swift] 자동 참조 카운트 (0) | 2024.04.02 |
---|---|
[Swift] 제네릭 (0) | 2024.04.02 |
[Swift] 에러 처리 (0) | 2024.03.28 |
[Swift] 옵셔널 체이닝 (0) | 2024.03.26 |
[Swift] 초기화 (1) | 2024.03.25 |
댓글