1. Protocol(프로토콜)
-프로토콜은 특정 기능을 수행하기 위한 메서드, 프로퍼티 등 요소들을 정의해 놓은 청사진을 말한다.
-프로토콜은 정의와 제시를 할 뿐 원하는 특정 기능 구현을 제공하지는 않고, 클래스, 구조체 또는 열거형에서 프로토콜을 채택하여 특정 기능을 실제 구현할 수 있다.
ex) 프로토콜 정의
protocol Example {
}
ex) 프로토콜 채택
struct ExamStruct : Example {
}
class ExamClass : Example {
}
enum ExamEnum : Example {
}
-extension을 통해 프로토콜에 추가적인 기능을 더해줄 수 있다.
-다른 프로토콜을 상속받을 수도 있다.(다중 상속도 가능)
프로토콜에서 프로퍼티 요구사항
1. 이름과 타입만 명시해주어야 하고(프로토콜은 정의나 제시만 할 뿐),
2. 각 프로퍼티에 읽기 전용으로 할지 쓰기 전용으로 할 지 get과 set을 명시해주어야 하고,
3. 선언 시 항상 var로 선언해야 한다.
ex) 프로퍼티 선언
protocol TestProcotol {
var testProperty : Int {get}
var secondTestProperty : Int {get, set}
static var thirdTestProperty : Int {get, set} //타입 프로퍼티
}
클래스의 타입 프로퍼티에는 상속이 가능한 class 타입과 상속이 불 가능한 static 타입이 있는데, 프로토콜에서는 이를 구분하지 않고 static을 사용한다.
ex) 프로토콜 채택
struct Example : TestProtocol {
var testProperty : Int
var secondTestProperty : Int
static var thirdTestProperty : Int = 0 //타입 프로퍼티는 이니셜라이저가 필요
}
위의 코드에서 TestProtocol의 프로퍼티 요구사항을 구조체 Example이 준수하고 있는 것!
프로토콜은 프로퍼티가 저장 프로퍼티인지, 연산 프로퍼티인지 명시할 필요없이 이름과 타입만이 요구된다!
프로토콜에서 프로퍼티를 명시할 때 gettable만 명시할 때와 gettable/settable 모두 명시했을 때의 차이
protocol TestProtocol {
var name : String {get}
}
위의 코드와 같이 프로퍼티를 get으로만 명시해주면 모든 종류의 프로퍼티에서 요구사항을 충족시킬 수 있다. (요구사항을 정의해줄 때 let 저장 프로퍼티든 var 저장 프로퍼티든, get이든 set이든 모두 충족)
ex) let과 var 저장 프로퍼티
struct Person : TestProtocol {
let name : String = "Lim"
}
struct Person : TestProtocol {
var name : String = "Lim"
}
let으로 정의하든 var로 정의하든 모두 가능!
ex) get과 set
struct Person : TestProtocol {
var name : String
var myName : String { //get
return name
}set {
name = newValue //set
}
}
var jisu = Persom(name : "jisu")
jisu.myName = "taehwan" //set 가능
print(jisu.myName) //get 가능
위의 코드와 같이 get으로 명시했을 때 let과 var 저장 프로퍼티, get과 set 연산 프로퍼티 모두 충족된다.
하지만 gettable/settable 로 명시했을 때는 모두 충족시킬 수 없다.
ex) get/set으로 명시했을 때
protocol TestProtocol {
var name : String {get set}
}
ex) 저장 프로퍼티로 요구사항 구현할 때
struct Person : TestProtocol {
let name : String = "Lim" //'let' 으로 선언된 저장 프로퍼티 error 발생!!
}
let으로 저장프로퍼티 충족은 불가!
ex) get 전용 연산프로퍼티로 요구사항 구현할 때
struct Person : TestProtocol {
var name : String
var myName : String { //gettable 만 충족하면 error 발생!
return name
}
}
get 전용 연산프로퍼티로 요구사항 충족 불가! get/set 모두 충족해주어야 한다.
프로토콜에서 메서드 요구사항
-프로토콜에서 메서드는
1. 타입 메서드와 특정 인스턴스 메서드를 요구할 수 있다.
2. 메서드의 실제 구현 부인 중괄호와 본문은 제외한다. (매개변수나 반환타입은 작성 가능)
protocol TestProcotol {
static func testTypeMethod()
func test() -> Double // {}는 입력안해줌.
}
ex) 채택할 때
class Example: TestProtocol {
static func testTypeMethod() {
}
func test() -> Double {
return 5.5
}
}
채택하는 곳에서 함수의 바디를 직접 구현!
Mutating 메서드 요구사항
Value Type인 구조체나 열거형의 메서드 앞에 "mutating" 을 붙여주면 프로퍼티의 값을 자유롭게 수정해 줄 수 있다.
프로토콜에서도 mutating 키워드를 붙여 메서드를 명시해주면, 구조체나 열거형에서 채택할 때 프로퍼티 수정이 가능한 메서드를 사용할 수 있다.
ex) struct에서 protocol 채택할 때
protocol ChangeNameProtocol {
mutating func changeName(name : String)
}
struct Person : ChangeNameProtocol {
var name : String = "jisu"
mutating func changeName(newName : String) {
name = "\(newName) + \(name)"
}
}
이렇게 Value Type에서 보통 메서드라면 메서드 안에서 프로퍼티의 값을 변경해줄 수 없지만, mutating을 통해서 수정가능해졌다.
ex) class에서 mutating이 있는 protocol을 채택할 때
class Person : ChangeNameProtocol {
var name : String = "jisu"
func changeName(newName : String) {
name = "\(newName) + \(name)"
}
}
class에서 채택할 때는 mutating을 붙이지 않아도 된다. 왜냐면 class는 Reference Type이기 때문에 애초에 mutating이 있던 말던 메서드에서 프로퍼티의 값을 변경하는 것이 가능하다!
참고:
프로토콜 (Protocols) - The Swift Language Guide (한국어) (gitbook.io)
Swift ) Protocols (1) (tistory.com)
Swift ) Protocols (2) (tistory.com)
Swift) Protocol 이해하기 (2/5) - 프로퍼티 / 메서드 선언 이해하기 (tistory.com)
'Swift' 카테고리의 다른 글
오버라이딩(Overriding)에 관하여 (0) | 2023.01.26 |
---|---|
제네릭(Generic)에 관하여 (0) | 2022.11.23 |
lazy variables에 관하여 (0) | 2022.10.07 |
순환참조에 관하여 (0) | 2022.09.28 |
@escaping에 관하여 (0) | 2022.08.25 |