Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
Tags
- 프로그래머스 n의 배수 고르기
- 문자열 붙여서 출력하기
- 조건에 맞게 수열 변경하기 3
- array
- 스파르타코딩캠프
- 프로그래머스 주사위 게임1
- 주사위 게임1
- Break
- Error installing cocoapods
- Til
- 연산자
- 프로그래머스 최댓값 만들기(2)
- 프로그래머스 조건에 맞게 수열 변경하기 3
- n번째 원소까지
- 배열 만들기1
- cocoapods 설치 오류
- continue
- 프로그래머스 n번째 원소까지
- 프로그래머스 암호 해독
- 프로그래머스 문자열 붙여서 출력하기
- 문자열 정렬하기 (1)
- ruby설치
- 프로그래머스 문자열 정렬하기 (1)
- 프로그래머스 자동커밋
- 객체지향
- swift
- 프로그래머스 배열 만들기1
- 스파르타 코딩클럽 내일배움캠프
- 프로그래머스
- 스페인어
Archives
- Today
- Total
dev._.note
[Swift] 프로토콜(Protocol) 본문
📌 프로토콜(Protocol)
프로토콜이란?
특정 역할(기능)을 하기 위한 메서드, 프로퍼티, 기타 요구사항의 청사진을 정의한 것.
프로토콜은 기능을 정의하고 제시할 뿐, 스스로 기능을 구현하지 않음.
- 구조체/클래스/열거형은 특정 프로토콜을 채택(adopted)해서 그 역할을 위한 요구사항을 구현.
- 어떤 타입이 어떤 프로토콜의 요구사항을 따르면, '해당 프로토콜을 준수한다(conform)'라고 표현.
스위프트에서 프로토콜은 완전한 하나의 타입으로 사용.
- 파라미터나 리턴타입으로 사용 가능
- 프로퍼티, 변수, 상수의 타입으로 사용 가능
- 배열 등 컨테이너 요소의 타입으로 사용 가능
protocol 프로토콜이름 {
프로토콜 정의
}
프로퍼티 요구사항
- 프로퍼티와 타입 프로퍼티 요구 가능
- 프로퍼티 요구사항은 항상 var로 선언
- 프로퍼티를 읽기 전용({ get }) 으로 할지, 읽고 쓰기({ get, set })로 할지 정해줘야 함
- 구현할 때는 프로퍼티의 이름과 타입만 맞으면 됨
- 타입 프로퍼티는 static 키워드를 사용해 선언
protocol SomeProtocol {
var settableProperty: String { get set }
var notNeedToBeSettableProperty: String { get }
static var typeProperty: Int { get }
}
메서드 요구사항
- 인스턴스 메서드 또는 타입 메서드 요구 가능
- 메서드에서 함수 body를 제외하고 시그니처만 작성
- 타입 메서드는 static 키워드 사용
protocol Sendable {
var from: Sendable { get }
func send(data: Any)
static func isSendableInstance(_ instance: Any) -> Bool
}
가변 메서드 요구 mutating method requirements
- 값 타입(구조체, 열거형)의 인스턴스 메서드에서 자신 내부의 값을 변경할 때 func 앞에 mutating으로 선언.
- 가변 메서드를 요구한 프로토콜을 클래스가 구현할 때는 mutating 키워드를 생략.
- 프로토콜에서 가변 메서드를 요구하지 않는다면, mutating 메서드는 구현이 불가능.
protocol Resettable {
mutating func reset()
}
struct Point: Resettable {
var x: Int = 0
var y: Int = 0
mutating func reset() {
self.x = 0
self.y = 0
}
}
이니셜라이저 요구
- 메서드와 마찬가지로 이니셜라이저의 매개변수만 지정하고, body는 구현하지 않음.
- 클래스 타입에서 프로토콜이 요구한 이니셜라이저를 구현할 때는 required 키워드를 붙인 요구 이니셜라이저로 구현.
- 해당 클래스를 상속받는 모든 클래스는 같은 프로토콜과 요구 이니셜라이저를 구현해야 하기 때문.
- 상속할 수 없는 final 클래스라면 required를 생략 가능.
- 프로토콜이 요구한 이니셜라이저가 구현된 클래스를 상속받은 클래스에서는 required override를 모두 명시해야 함
- 실패 가능한 이니셜라이저도 요구 가능
protocol Name {
var name: String { get }
init(name: String)
}
class Person: Named {
var name: String
required init(name: String) {
self.name = name
}
}
프로토콜 채택하기
- 구조체, 클래스, 열거형 등에서 타입 이름 뒤에 콜론을 붙인 후, 채택할 프로토콜을 쉼표로 나열함
- 클래스 상속도 함께 받는 경우, 상속받는 클래스 이름 다음에 프로토콜 나열
struct SomeStruct: AProtocol, AnotherProtocol {
}
프로토콜의 상속
- 프로토콜끼리도 상속이 가능.
- 문법은 클래스 상속 문법과 유사.
- 구현할 때는 상속받은 프로토콜의 요구사항까지 모두 구현.
protocol Readable {
func read()
}
protocol Writeable {
func write()
}
protocol ReadWriteSpeakable: Readable, Writeable {
func speak()
}
클래스 전용 프로토콜
- 프로토콜의 상속 리스트에 class 키워드를 추가하면, 프로토콜이 클래스 타입에만 채택될 수 있도록 제한할 수 있음.
- 맨 처음에 class 키워드를 작성해야 함.
protocol ClassOnlyProtocol: class, Readable, Writeable {
// 이 프로토콜은 클래스에서만 채택 가능
}
프로토콜 조합(composition)
- 매개변수 타입에 여러 프로토콜을 한 번에 조합하여 요구할 수 있음
- 주어진 프로토콜을 모두 준수해야 함
- 매개변수 하나가 프로토콜을 둘 이상 요구할 수 있음
- 특정 클래스의 인스턴스 역할을 할 수 있는지도 함께 확인할 수 있음
- 단, 클래스는 한 타입만 조합할 수 있음
protocol Named {
var name: String { get }
}
protocol Aged {
var age: Int { get }
}
func celebrateBirthday(to celebrator: Named & Aged) {
print("Happy Birthday \(celebrator.name)! Now you ard \(celebrator.age)")
}
class Car: Named {
var name: String
init(name: String) {
self.name = name
}
}
var someVariable: Car & Named
프로토콜 준수 확인
타입캐스팅의 is, as 연산자로 대상이 프로토콜을 준수하는지 확인하거나, 특정 프로토콜로 캐스팅 가능.
- is : 해당 인스턴스가 프로토콜을 준수하는지 확인
- as? : 다른 프로토콜로 다운캐스팅 시도
- as! : 다른 프로토콜로 강제 다운캐스팅
struct Person: Named, Aged {
var name: String
var age: Int
}
let bibi: Person = Person(name: "bibi", age: 99)
print(bibi is Named) // true
print(bibi is Aged) // true
if let castedInstance: Name = bibi as Named {
print("\(castedInstance) is Named")
} // Person is Named
프로토콜 변수와 상수
- 프로토콜을 타입으로 갖는 변수/상수에는, 그 프로토콜을 준수하는 타입의 어떤 인스턴스든 할당 가능.
- 프로토콜만으로 스스로 인스턴스 생성 및 초기화 불가능.
위임을 위한 프로토콜 (Delegation)
- 위임(Delegation 델리게이션) : 클래스나 구조체가 자신의 책임을 다른 인스턴스에게 위임하는 디자인 패턴.
- 책임을 수행하도록 정의한 프로토콜을 준수하는 타입은 그 책임을 수행함이 보장되므로, 프로토콜을 준수할 때 책임을 위임가능.
- 위임 패턴은 애플 프레임워크에서 사용하는 주요 패턴이다.
- 다양한 프로토콜이 "... Delegate"와 같은 이름으로 정의.
- 예) UITableView 타입의 인스턴스가 할 일을 위임받아 처리하는 인스턴스는 UITableViewDelegate 프로토콜을 준수.
'Dev > SWIFT' 카테고리의 다른 글
[Swift] 강한 참조 순환 문제와 해결방법 (1) | 2023.12.15 |
---|---|
[Swift] 스레드(Thread) (0) | 2023.12.14 |
[Swift] ARC(Automatic Reference Counting) (0) | 2023.12.12 |
[Swift] 예외처리 (0) | 2023.12.11 |
[Swift] 클로저(Closure) (0) | 2023.12.10 |