티스토리 뷰

프로토콜(Protocol)

API를 더욱 간결하게 표현하는 방법이며 하나의 타입

클래스와 구조체를 완전하게 구현해놓지 않고 클래스와 구조체가 무엇에 대한것인지만 밝혀둠

프로토콜은 선언된 메소드와 프로퍼티로 된 집합체

타입을 사용하는 곳이라면 어디든 사용 가능

프로토콜을 실행하는 클래스(class, struct, enum등) 안에서 실행

프로토콜의 일부나 전부를 실행하기 위해 extension을 사용하는 것도 가능(extension protocol 선언)

저장 공간을 갖지 않음(계산 프로퍼티만 가질 수 있음)

 

프로토콜을 사용하기 위한 단계

1. 프로토콜 선언 : 프로토콜에 들어갈 메소드, 프로퍼티 선언

2. 클래스, 구조체, enum 중 하나에서의 프로토콜 실행 선언

3. 프로토콜 실행

 

Optional methods in a protocol

Swift에 있는 프로토콜과 모든 프로퍼티와 모든 메소드는 반드시 있어야 함

프로토콜을 실행한다고 하면 프로토콜 전부를 실행해야함(선택적 실행 불가)

Objective-C의 프로토콜은 선택적일 수 있음(optional func : 실행해도 되고 안해도 괜찮음)

이렇게 선택적으로 실행하고 싶으면 프로토콜을 @objc 형태로 선언하면 됨

이런 프로토콜 안에서는 optional키워드를 func나 var 앞에 붙여줄 수 있음

이러한 기능은 iOS의 delegation에서 이용됨

클래스를 실행하는 모든 선택적 프로토콜은 NSObject로부터 상속받아야함

 

프로토콜은 다중 상속을 받을 수 있음

프로토콜이 다른 프로토콜로부터 상속받는다는 것 

= SomeProtocol을 실행하고 싶은 사람은 상속받는 프로토콜도 함께 실행해야 한다는 의미

프로토콜 안에 변수가 있을 때 get only인지 get and set인지 명시 필요

바뀔 예정인 모든 함수들은 mutating - struct가 프로토콜 실행할 수도 있음

** mutating은 value type이며 기본적으로 인스턴스 메서드로 내부값 수정 불가. 내부값 변경 필요할 때 mutating 키워드 사용

protocol SomeProtocol : InheritedProtocol1, InheritedProtocol2 {
    var someProperty: Int { get set }
    func aMethod(arg1: Double, anotherArgument: String) -> SomeType
    mutating func changeIt()
    init(arg: Type)
}

프로토콜을 제한하는 것도 가능

예시 : enum과 struct는 프로토콜 실행 못하도록 class 키워드 삽입

프로토콜 안에 초기화 함수 삽입 가능 → 프로토콜을 사용하는 누구던 이렇게 생긴 이니셜라이저를 가지고 있어야 함

protocol SomeProtocol : class, InheritedProtocol1, InheritedProtocol2 {
    var someProperty: Int { get set }
    func aMethod(arg1: Double, anotherArgument: String) -> SomeType
    // mutating func changeIt() class는 mutating 필요없음
    init(arg: Type)
}

프로토콜의 실행

class SomeClass : SuperclassSomeClass, SomeProtocol, AnotherProtocol {
	required init(...)
}

프로토콜을 선언하는 것은 프로토콜을 실행하겠다고 약속하는 의미

enum의 경우 부모클래스 없으며 프로토콜의 개수제한 없음

프로토콜에 init이 있고 클래스가 그것을 실행하면 required로 만들어야 함

→ 자식 클래스는 이 프로토콜을 실행한다는 사실을 상속받기 때문임

 

extension을 통해 프로토콜 적용 추가 가능

extension Something : SomeProtocol { ... }

프로토콜 사용 예시

protocol Moveable {
    mutating func moveTo(p: CGPoint)
}
class Car : Moveable {
    func moveTo(p: CGPoint) { ... }
    func changeOil()
}
struct Shape : Moveable{
    mutating func moveTo(p: CGPoint) { ... }
    func draw()
}

let prius: Car = Car()
let squre: Shape = Shape()

var thingToMove: Moveable = prius
thingToMove.moveTo(...) //car에 있는 moveTo 호출
thingToMove.changeOil() //불가능. thingToMove는 Car가 아닌 Moveable임
thingToMove = squre
let thingsToMove: [Moveable] = [prius, squre]

func slide(slider: Moveable){
    let positionToSlideTo = ...
    slider.moveTo(positionToSlideTo)
}
slide(prius)
slide(squre)

func slipAndSlide(x: protocol<Slippery, Moveable>) //두가지 프로토콜 모두 실행 필요
slipAndSlide(prius) //불가능 프로토콜 하나만 따르고 있음

 

최근에 올라온 글
Total
Today
Yesterday