프로토콜 안의 프로퍼티 / 메서드는 모두 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!")
}
}