프로토콜
프로토콜이란? 일종의 강제사항으로 해당 프로토콜을 채택한 객체는 프로토콜이 요구하는 내용을 반드시 준수해야만 한다.
프로토콜은 단순한 선언 형태로만 작성되며 구체적인 내용은 프로토콜을 채택한 객체가 담당한다.
프로토콜은 프로토콜을 상속받을 수 있다. 그리고 프로토콜은 다중상속이 가능하다.
프로토콜은 static, mutating 등의 키워드 사용이 가능하다.
protocol Test {
var number: Int { get set } //읽고 쓰기가 가능한 저장 프로퍼티 선언
var number2: Int { get } //읽기만 가능한 연산 프로퍼티로 선언
func add(num1: Int, num2: Int) -> Int //정수타입을 매개변수로 하여 정수를 반환하는 메소드를 선언
}
class A: Test {
var name: String = "이름" //새로운 프로퍼티
var number: Int = 10 //저장 프로퍼티 구현(프로토콜 요구사항)
var number2: Int { //연산 프로퍼티 구현(프로토콜 요구사항)
get {
return 3
}
}
func add(num1: Int, num2: Int) -> Int { //메소드 구현(프로토콜 요구사항)
return num1 + num2
}
}
프로토콜이 요구하는 내용을 준수하기만 한다면, 새로운 프로퍼티나 메소드를 추가하는 것은 상관이 없다. 이처럼 프로토콜은 채택한 객체가 그 구현을 담당한다.
프로토콜의 초기화 메소드
클래스나 구조체에서 아무런 초기화 메소드를 정의하지 않을 경우 기본적으로 제공되는 초기화 메소드도 프로토콜에 정의되어 있다면 반드시 구현해야 한다. 클래스에서 초기화 메소드를 구현할 때에는 반드시 required 키워드를 붙여야 한다.
protocol A {
init()
init(name: String)
}
struct B: A {
var name: String?
init() {
self.name = "default"
}
init(name: String) {
self.name = name
}
}
class C: A {
var name: String?
required init() {
self.name = "default"
}
required init(name: String) {
self.name = name
}
}
클래스의 경우 상속과 프로토콜 채택이 동시에 가능하기 때문에 상속과 채택에 따른 override와 required를 동시 써야한다.
이때 작성되는 순서는 중요하지 않다.
protocol A {
init()
}
class B {
init () {
}
}
class C: B, A {
override required init() {
}
}
클래스와 프로토콜
클래스 전용 프로토콜을 선언할 수 있는데, 이때에는 프로토콜 이름 다음에 class를 추가한다.
또한, 클래스 전용 프로토콜의 경우 옵셔널로 선언한 내용에 대해서는 반드시 구현하지 않아도 된다.
옵셔널로 선언할 경우에는 반드시 @objc 키워드를 추가해야 한다.
import Foundation
@objc
protocol A: class {
@objc optional var name: String { get set }
}
class B: A {
}
이처럼 옵셔널 변수 name의 구현은 구현하는 객체의 자유이다.