프로토콜
안의 프로퍼티
/ 메서드
는 모두 require
이다. 따라서 기본값으로 세팅을 하거나 채택하는 곳에서 구현하지 않으면 에러가 난다.
만약에 옵셔널
로 형을 지정해놓고, 값을 할당해주지 않는다 하더라도 그것도 기본값으로 세팅을 한거다. 옵셔널
자료형은 초기화가 되지 않을 시에 nil
로 자동 초기화된다.
클래스의 경우에 초기화를 하지 않더라도, 기본초기화자가 있기 때문에 괜찮다. ( 아주 괜찮다는건 아니고 )
프로토콜은 타입
이다.
@objc optional
을 붙인다.@objc optional
을 붙이고, 프로토콜 앞에도 @objc
를 붙여 선언한다. @objc protocol Band : AnyObject{
var drum : String { get set }
var vocal : String { get set }
var piano : String { get set }
@objc optional var bass : String { get set }
func play()
}
프로토콜에 선언되는 프로퍼티는 항상 var
로 선언되어야 한다.
구조체의 경우, mutating
이 필요하면 프로토콜 자체에 추가
ㄴ 메서드 안에서 프로퍼티 값을 변경해야할 경우 반드시 mutating
키워드를 func 앞에 붙여줘야 한다.
protocol Renameable{
mutating func changeName(newName : String)
}
struct Sodeul : Renameable{
var name : String = "Johnson"
mutating func changeName(newName : String){
self.name = newName
}
}
class DeulSo : Renameable{
var name : String = "sodeul"
func changeName(newName : String){
self.name = newName
}
}
protocol Band{}
protocol Solo{}
struct Beatles : Band{}
let beatles = Beatles.init()
beatles is Band // true
beatles is Solo // false
여러개의 클래스가 프로토콜을 채택할 수 있다.
해당 클래스들에서 공통적으로 play()
라는 메서드를 구현하고 있다고 쳐보자. 근데, 기본적으로 비슷한 동작을 하고 5개가 한다고 하면 이 중에 1개만이 다른 동작을 하고 있다고 쳐보자.
참고로 프로토콜
에 선언된 메서드는 기본값을 가질 수 없다.
그렇다면 protocol에서
protocol ExampleProtocol{
func play() -> Void
}
가 있다고 했을 때 확장을 해서 이 프로토콜의 메서드 기본동작을 지정해 줄 수 있다.
protocol ExampleProtocol{
func play() -> Void
}
extension ExampleProtocol{
func play() -> Void{
print("play")
}
}
이후에는 구현하지 않고 바로 사용하면 사전에 확장에 포함된 메서드가 실행되게 된다.
원치 않을 경우에는 구현하면 된다.
where
를 통해서 기본 메서드를 제공하는 것에 제한을 둘 수도 있다.
protocol Human{}
protocol Band{
func play()
}
extension Band where Self : Human{
func play() {
print("play!")
}
}