본문은 야곰 아카데미 커리어 스타터 캠프를 통해 학습한 내용을 회고한 글입니다.
프로토콜 Protocol
프로토콜은 특정 일이나 함수에 걸맞는 메서드, 프로퍼티, 그리고 다른 요건들의 청사진을 정의한다. 프로토콜은 요건들의 구현을 제공하기 위해서 클래스, 구조체, 열거형에서 사용될 수 있다. 프로토콜의 요건들을 충족하는 어떤 타입이든지 프로토콜을 따른다고 말할 수 있다.
필수적으로 구현해야하는 타입들을 따르는 요건들을 명시하는 것 뿐만 아니라, 그러한 요건들을 구현하기 위해서 혹은 추가적인 함수를 구현하기 위해서 프로토콜을 확장할 수도 있다.
프로토콜 문법 Protocol Syntax
프로토콜은 클래스, 구조체, 열거형과 비슷한 방식으로 정의할 수 있다:
protocol SomeProtocol {
// protocol definition goes here
}
커스텀 타입은 타입의 이름 뒤에 프로토콜의 이름을 적음으로서 프로토콜을 사용한다고 명시할 수 있다. 쉼표(,)를 통해서 여러 개의 프로토콜이 나열 될 수 있다.
struct SomeStructure: FirstProtocol, AnotherProtocol {
// structure definition goes here
}
만약에 클래스가 슈퍼클래스를 가진다면, 프로토콜 앞에 슈퍼클래스 이름을 써주면 된다.
class SomeClass: SomeSuperclass, FirstProtocol, AnotherProtocol {
// class definition goes here
}
프로퍼티 요건 Property Requirements
프로퍼티는 특정 이름과 타입을 가진 타입 프로퍼티나 인스턴스를 제공하기 위하여 적절한 타입을 요구할 수 있다. 프로토콜은 프로퍼티가 저장 프로퍼티여야하는지 연산 프로퍼티여야하는지를 명시하진 않는다. 오직 프로퍼티의 이름과 타입을 요구할 뿐이다. 또한 프로토콜은 각각의 프로퍼티가 gettable인지 gettable+settable인지를 명시한다.
만약 프로토콜의 프로퍼티가 gettable+settable이어야한다면, 그 프로퍼티 요건은 상수 저장 프로퍼티나 읽기전용 연산 프로퍼티로는 만족되지 못할 것이다. 만약 프로토콜의 프로퍼티가 gettable이어야한다면, 어떤 종류의 프로퍼티로든 그 프로퍼티의 요건이 만족될 것이다. 그리고 이것은 코드상으로 필요하다면 프로퍼티가 settable이 되는 것에 대해서도 유효하다.
프로퍼티 요건은 항상 변수 프로퍼티로 명시되어있다. gettable+settable 프로퍼티는 { get set }을, gettable은 { get }을 타입 명시 뒤에 씀으로서 명시된다.
protocol SomeProtocol {
var mustBeSettable: Int { get set }
var doesNotNeedToBeSettable: Int { get }
}
프로토콜에서 프로퍼티 요건을 정의할 때 타입 프로퍼티 요건으로 static 키워드를 써줘야한다. 클래스에서 구현되어서 타입 프로퍼티 요건이 class나 static 키워드가 붙을 수 있을 때에도 마찬가지로 적용된다.
protocol AnotherProtocol {
static var someTypeProperty: Int { get set }
}
다음은 단일 인스턴스 프로퍼티의 요건을 가진 프로토콜의 예시이다:
protocol FullyNamed {
var fullName: String { get }
}
FullyNamed 프로토콜은 완벽하게 적합한 이름을 제공하기 위해서 적절한 타입을 필요로 한다. 프로토콜은 적절한 타입의 특성에 대해서는 명시하지 않는다. 오직 그 타입이 그 자체로 풀네임을 제공할 수 있어야한다는 것만을 명시한다. 프로토콜은 어떠한 FullyNamed 타입이든간에 String 타입인 fullName이라는 gettable 인스턴스 프로퍼티를 가져야한다고 말한다.
struct Person: FullyNamed {
var fullName: String
}
let john = Person(fullName: "John Appleseed")
// john.fullName is "John Appleseed"
이 예시는 특정 이름을 가진 사람을 나타내는 Person이라는 구조체를 정의하고 있다. FullyNamed 프로토콜을 이 구조체 정의의 첫줄에서 그것을 사용한다는 것을 말해준다.
Person의 각각의 인스턴스는 String 타입인 fullName이라는 단일 저장 프로퍼티를 가진다. FullyNamed 프로토콜의 단일 요건에 부합하고, Person이 프로토콜을 완벽히 따른다는 것을 의미한다. (만약에 요건들이 충족되지 않으면 컴파일 타임 에러를 내뱉는다.)
FullyNamed 프로토콜을 사용하고 따르는 조금 더 복잡한 클래스를 보자:
class Starship: FullyNamed {
var prefix: String?
var name: String
init(name: String, prefix: String? = nil) {
self.name = name
self.prefix = prefix
}
var fullName: String {
return (prefix != nil ? prefix! + " " : "") + name
}
}
var ncc1701 = Starship(name: "Enterprise", prefix: "USS")
// ncc1701.fullName is "USS Enterprise"
이 클래스는 연산 읽기 전용 프로퍼티로 fullName 프로퍼티 요건을 구현한다. 각각의 Starship 클래스 인스턴스는 필수적인 이름과 옵셔널한 prefix를 저장한다. fullName 프로퍼티는 prefix 값이 존재하면 그 값을 사용하고, 우주선의 풀네임을 만들기 위해서 이름 앞에 붙여준다.
'YAGOM CAREER STARTER' 카테고리의 다른 글
[TIL] 20230113: Protocol2 (0) | 2023.01.14 |
---|---|
[TIL] 20230112: Closures (0) | 2023.01.13 |
[TIL] 20230109: Singleton (0) | 2023.01.10 |
[토요스터디A반] 20230107: Property Observer, MVC, Notification Center (0) | 2023.01.07 |
[TIL] 20230106: Modality/Navigation (0) | 2023.01.06 |