[swift] 11. 프로토콜 (protocol)
1. Delegate Pattern : 프로토콜을 쓰는 대표적인 이유
- 각종 이벤트를 효율적으로 관리하기 위해 대리자를 지정하여 이벤트 처리를 위임하고,
이벤트 발생시 위임된 대리자가 콜백 메소드를 호출하는 설계 패턴
* protocol : 명세
- protocol입장에서 구현 하는 객체가 어떤 객체인지 상관없고, "날 구현하여 특정 일을 시행하라"라는 의미
- 클래스는 단일 상속이기때문에 protocol이 나온 것
2. 프로토콜 생성
1) 프로토콜 프로퍼티 : 연산 프로퍼티만 가능하며 get, set유무만 표현
2) 프로토콜 메소드 : 구현부만 빼고 그대로 작성
|
1
2
3
4
5
6
7
8
9
10
11
|
// 프로토콜 프로퍼티
protocol myProtocol {
var a: String {get set}
var b: Int {get }
}
// 프로토콜 메소드
protocol myProtocol{
func myFunc(param: String)
}
|
3. 프로토콜 이용
1) 프로토콜에 선언된 메소드 모두를 구현해야 함
※ 단, 프로토콜 생성시 이름 앞에"@objc" 를 붙인 후, 꼭 구현하지 않아도 되는 메소드에는 "optional"키워드를 붙여서 선택적 구현을 하게끔 가능
|
1
2
3
|
@objc protocol myProtocol {
optional func myFunction(outParam inParam: Int) -> Int
}
|
2) 외부 매개변수 명은 protocol그대로 따라야 하며 내부 매개변수는 임의로 바꾸어도 됨
- protocol에서 mutating키워드로 선언되었더라도 실제 구현하는 객체에서 필요 없다면 안써도 됨
- static과 class키워드 역시 필수가 아님
|
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
|
// 프로토콜 프로퍼티
protocol myProtocol {
var a: String {get set}
func myFunc(outParam inParam : Int)->Void
}
class A : myProtocol {
var a: String{
get{
return "abc"
}
set{
}
}
func myFunc(outParam newParam: Int) {
print(newParam)
}
}
let instance: A = A()
print(instance.a) // "abc"
|
3) init작성 : 클래스에서 init()메소드를 구현할 때 required키워드를 붙여야함
|
1
2
3
4
5
6
7
8
9
10
11
|
// 프로토콜 프로퍼티
protocol myProtocol {
init()
}
class A : myProtocol {
required init(){
}
}
|
4) 타입으로서의 protocol : "&"로 표현
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
// 프로토콜 프로퍼티
protocol A {
}
protocol B {
}
class C : A, B{
}
var tmp: A & B = C()
|
4. 특정 클래스에 extension으로 protocol추가하기
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
class Person {
}
protocol Performance {
func work () -> ()
}
extension Person : Performance {
func work () -> () {
print("working!")
}
}
let kim = Person()
|
5. protocol 제약 주기
1) 클래스 전용 protocol : 정의시, class를 붙임
|
1
2
3
|
protocol Person : class {
}
|
2) optional 키워드를 사용하려면, 프로토콜 앞에 @objc 붙임(단, 클래스에서만 이 프로토콜 구현가능)
|
1
2
3
4
5
6
7
|
import Foundation
@objc
protocol A {
@objc optional func myFunc(param: Int)
}
|
※ 접근 시, 메소드 이름 끝에다 '?'붙여야함 (메소드 자체가 옵셔널 타입이므로)
myFunc?(param: 123)