프로토콜의 기본 문법
- 정의 -> 채택 -> 구현
- 정의
- 프로토콜을 만들어 필요한 요구사항을 담음
- 채택
- 프로토콜 채택 (클래스, 구조체, 열거형에서 채택가능)
- 구현
- 프로토콜에서 요구하는 사항을 직접 구현
protocol SomeProtocol { // 프로토콜 정의
func doSomething(num: Int) -> Int // 메서드의 구현이 아닌 요구사항만 정의
// func doSomething() { } (구현는 프로토콜을 채택한 곳에서 함)
}
class AClass: SomeProtocol { // 프로토콜 채택
// 프로토콜 채택시 프로토콜의 요구사항을 반드시 구현해야함
func doSomething(num: Int) -> Int {
return num
}
}
struct AStruct: SomeProtocol { // 구조체에서 채택
// 프로토콜 채택시 프로토콜의 요구사항을 반드시 구현해야함
func doSomething(num: Int) -> Int {
return num
}
}
enum AEnum: SomeProtocol { // 열거형에서 채택
func doSomething(num: Int) -> Int {
return 0
}
}
프로토콜 요구사항 정의
- 속성의 요구사항
- 최소한의 요구사항 지정
- 저장속성/계산속성 모두 구현 가능 (프로토콜의 요구사항만으로는 저장/계산속성의 구별 불가능)
- 인스턴스 속성 요구사항
- {get} -> 저장속성: let / var
-> 계산속성: 읽기(get) / 읽기쓰기(get,set)
- {get set} -> 저장속성: var
-> 계산속성: 읽기쓰기(get,set)
protocol SomeProtocol { // 프로토콜 정의
var num: Int { get } // 읽기 (최소한의 요구사항이기때문에 구현시 읽기쓰기 형식으로도 구현가능)
var name: String { get set } // 읽기쓰기 (읽기만 구현 불가능)
var age: Int { get }
static var type: String { get set } // 타입속성
}
class AClass: SomeProtocol { // 프로토콜 채택
// 프로토콜의 속성의 요구사항 구현
let num = 10 // var으로도 구현가능
var name = "Jimin" // let으로는 구현 불가능
static var type = "Some Type"
// 프로토콜의 정의에서는 속성이 계산속성인지 저장속성인지 구별 불가능
// 즉, 구현시 계산속성으로 구현도 쌉가능
var age: Int {
return 24
}
}
- 메서드의 요구사항 정의
- 메서드의 헤드부분(인풋, 아웃풋)까지만 정의
- 구조체에서 저장속성 변경하는경우 mutating 키워드 붙임 (구조체로 제한하는것은 아님)
protocol SomeProtocol { // 프로토콜 정의
func randomNum() -> Int // 메서드의 헤드부분(인풋, 아웃풋)까지만 정의
mutating func changeNum(_ num: Int) // 구조체에서 저장속성 변경시 mutating키워드 붙임
static func doSomething() // 타입속성
}
class AClass: SomeProtocol {
var num = 0
func randomNum() -> Int {
return Int.random(in: 1...100)
}
// 프로토콜 정의 부분에 mutating 키워드가 있어도 클래스에서 구현 가능
func changeNum(_ num: Int) {
self.num = num
}
static func doSomething() {
print("doSomething")
}
}
struct AStruct: SomeProtocol {
var num = 0
func randomNum() -> Int {
// self.num = 10 (프로토콜 정의에 mutating 키워드 없으면 저장속성 변경 불가)
return Int.random(in: 1...100)
}
mutating func changeNum(_ num: Int) {
self.num = num
}
static func doSomething() {
print("doSomething")
}
}
프로토콜은 확장에서 구현하는게 국룰임
protocol SomeProtocol { // 프로토콜 정의
func randomNum() -> Int // 메서드의 헤드부분(인풋, 아웃풋)까지만 정의
mutating func changeNum(_ num: Int) // 구조체에서 저장속성 변경시 mutating키워드 붙임
static func doSomething() // 타입속성
}
class AClass {
var num = 0
}
// 프로토콜은 확장(extension)에서 구현하는게 일반적이다
extension AClass: SomeProtocol {
func randomNum() -> Int {
return Int.random(in: 1...100)
}
// 프로토콜 정의 부분에 mutating 키워드가 있어도 클래스에서 구현 가능
func changeNum(_ num: Int) {
self.num = num
}
static func doSomething() {
print("doSomething")
}
}
상속과 프로토콜 채택을 같이할때는 상속먼저
protocol SomeProtocol { } // 프로토콜 정의
class SomeClass { }
// 상속과 프로토콜 채택을 같이할때는 상속먼저
class AClass: SomeClass, SomeProtocol { }
프로토콜은 다중채택 쌉가능
protocol SomeProtocol { }
protocol SomeProtocol2 { }
// 프로토콜은 다중채택 가능
class AClass: SomeProtocol, SomeProtocol2 { }
프로토콜의 선택적 구현
// 프로토콜 앞에 @objc 키워드 붙이기
@objc protocol Remote {
// 선택적으로 구현을 하고싶은 요구사항 앞에 @objc optional 키워드 붙이기
@objc optional func turnOn()
func turnOff()
}
class AClass: Remote {
func turnOff() {
print("꺼짐")
}
/*
@objc optional 키워드가 붙으면 구현을 선택적으로 해도 된다
func turnOn() {
}
*/
}
'Swift > 문법' 카테고리의 다른 글
[Swift] 프로토콜 (3/4) 프로토콜의 상속 (0) | 2022.04.16 |
---|---|
[Swift] 프로토콜 (2/4) 타입으로써의 프로토콜 (0) | 2022.04.16 |
[Swift] 확장 (extension) (0) | 2022.04.10 |
[Swift] 타입캐스팅 (is, as?, as! 연산자) (0) | 2022.04.09 |
[Swift] 초기화(Initialization)와 생성자(Initializer) (5/5) 필수생성자, 실패가능생성자, 소멸자 (0) | 2022.04.09 |