벚꽃이 만개한 남산뷰
구조체 클래스 열거형은 프로토콜을 채택해서 특정 기능을 실행하기 위한 프로토콜의 요구사항을 실제로 구현할 수 있다.
이때 모든 요구사항을 충족하면 해당 타입이 채택한 프로토콜을 준수하다고 볼 수 있다.
protocol SomeProtocol {
}
protocol SomeProtocol2 {
}
struct SomeStruct: SomeProtocol, SomeProtocol2 {
}
구조체에서 프로토콜을 여러개를 받아올 수 있다. 쉼표로 구분하며 구조체 이름 옆에 나열해주면 된다.
프로토콜은 자신을 채택한 타입이 어떤 프로퍼티인지 요구할 수 있다. 프로토콜이 프로퍼티에 준수하도록 정의할 때 저장프로퍼티인지 계산프로퍼티인지 정하지 않고 프로퍼티이름과 타입만 지정하면된다. 그리고 프로퍼티에 읽기만 가능한 프로퍼티인지, 읽기 쓰기가 가능한 프로퍼티인지 get과 set으로 지정해줘야한다.
protocol FirstProtocol {
var name: Int { get set }
var age: Int { get }
}
프로토콜이 프로퍼티를 요구할 때 항상 var키워드 즉, 변수로 요구해야하고 읽기 쓰기가 가능한 프로퍼티는 name프로퍼티와 같이 타입 선언 후 { get set }
을 작성하면 된다. 읽기 전용일 경우 타입 뒤에 { get }
을 작성해주면 된다.
protocol AnotherProtocol {
static var someTypeProperty: Int { get, set }
}
프로토콜에서 타입 프로퍼티를 요구하려면 항상 static 키워드를 써줘야한다.
protocol FullyNames {
var fullName: String { get set}
}
struct Person: FullyNames {
var fullName: String
}
만약 위에 구조체에서 fullname을 작성해주지 않으면 Type 'Person' does not conform to protocol 'FullyNames'
에러가 나온다. person은 FullyNames가 요구하는 읽기 쓰기가 가능한 fullName이 없다는 뜻이라 안에 var fullName: String
를 넣어주면 에러가 해결 된다.
추가로 프로토콜은 자신을 채택한 타입에 매서드를 요구할 수 있는데 이떄 요구할 수 있는 매서드는 인스턴스, 타입 매서드 모두 가능하다.
protocol FullyNames {
var fullName: String { get set}
func printFullName()
}
struct Person: FullyNames {
var fullName: String
func printFullName() {
print(fullName)
}
}
프로토콜은 자신을 채택한 타입에 생성자도 요구할 수 있다.
protocol SomeProtocol4: {
init(someParameter: Int)
}
이때 생성자의 키워드와 매개변수만 지정해주면 된다.
initialize를 코드로 해보면
protocol SomeProtocol5 {
init()
}
class SomeClass: SomeProtocol5 {
required init() {
}
}
클래스에서 프로토콜이 요구하는 생성자를 채택하려면 위와 같이 required 식별자를 사용해야한다.
구조체에선 required가 필요없지만 클래스에선 필요하다. 만약 final 키워드가 붙어있는 class라면 굳이 required를 해줄 필요가 없다.