프로토콜에 대해 기본적인 개념을 파악했다면 이를 정의하는 방법은 어떻게 되는지 알아보려고한다.
protocol RemoteMouse {
var id: String { get }
var name: String { get set }
static var type: String { get set }
class var type: String { get set }
}
var 저장 속성을 가지며, { get } 과 { get set } 으로 각각 읽기, 읽기/쓰기 용도로 구현할 수 있다.
해당 조건으로 프로토콜을 채택하게되면 아래와 같은 코드가 된다.
struct SamSungTV: RemoteMouse {
var id: String = "1"
var name: String = "Samsung TV"
static var type: String = "리모콘"
}
struct LGTV: RemoteMouse {
let id: String = "1"
var name: String = "LG TV"
static var type: String = "리모콘"
}
실제로 위에서 { get } 으로 선언 되어있는 경우, TV 구조체의 속성 id를 저장속성으로 구현할 경우 let으로도 구현할 수 있다.
하지만 속성 name의 경우에는 { get set } 으로 선언되어 있어, 오로지 var 변수 저장 속성만이 가능하다.
계산 속성으로 구현할 경우에는 { get } 으로 선언한 경우에는 getter만 만들거나, getter setter 모두를 생성할 수 있다.
하지만, { get set } 으로 선언된 경우에는 getter setter 모두 제공해야한다.
struct SamSungTV: RemoteMouse {
var id: String {
get {
return "1"
}
}
var name: String = "Samsung TV"
static var type: String = "리모콘"
}
struct LGTV: RemoteMouse {
var id: String {
get {
return "1"
}
set {
self.name = newValue
}
}
var name: String = "LG TV"
static var type: String = "리모콘"
}
struct AppleTV: RemoteMouse {
var id: String = "1"
var name: String {
get {
return "Apple TV"
}
set {
self.id = newValue
}
}
static var type: String = "리모콘"
}
*타입(static) 속성 요구사항
// 1) 저장 타입 속성으로 구현
class SmartPhone: RemoteMouse {
var id: String {
return "777"
}
var name: String {
get { "아이폰" }
set { }
}
static var type: String = "리모콘" // 타입 저장 속성은 (상속은 되지만) 재정의 원칙적 불가능
}
// 2) 계산 타입 속성으로 구현
class Ipad: RemoteMouse {
var id: String = "777"
var name: String = "아이패드"
class var type: String { // 타입 계산 속성은 재정의 가능 (class키워드 가능)
get { "리모콘" }
set { }
}
}
// 1) 정의
protocol RandomNumber {
static func reset()
func random() -> Int
}
// 2) 채택 / 3) 구현
class Number: RandomNumber {
static func reset() {
print("다시 셋팅")
}
func random() -> Int {
return Int.random(in: 1...100)
}
}
구조체의 경우 메서드 내에서 저장 속성의 값을 변경해야할 경우, mutating 을 선언해주어야한다. 이때, 프로토콜에 선언을 하고 구조체에서 채택할 경우 구조체 내에 함수내에도 mutating 가 선언되어야한다. 하지만 클래스의 경우에는 해당 키워드가 필요없으니 빼고 선언을 하면된다.
protocol Rename {
mutating func changeName(newName: String)
}
struct Name1: Rename {
var name: String = "Potter"
mutating func changeName(newName: String) {
self.name = newName
}
}
class Name2: Rename {
var name: String = "JiSung"
func changeName(newName: String) {
self.name = newName
}
}

실제로 실행할 경우 두 개의 모두의 저장 속성의 값이 변경되었다.
프로토콜의 내용이 너무 많고도 많지만 실제로 프로젝트에서도 적용해보고 사용하면서 내용을 새로 작성해보도록해봐야겠다!