protocolは、特定のタスクや機能に適したメソッド、プロパティ、その他の要件の設計図を定義します。とのことです。
設計図の定義ということですが、プロパティ名は作れても、値は設定できません。メソッド名は作れても処理を書くことはできません。値の設定や処理を書くことは、protocolに準拠したclass、struct、enumでしかできません。
また、継承はclassしかできません。protocolの場合は準拠というようです。
共通の要件を設定しようとしたとき、struct、enumではprotocolを使うしかありません。
ところで、classでは値の設定や、処理を書くことができるので、どの継承部分の設定や、処理を引き継いでいるか管理するのに大変そうです。
「何代前のご先祖様はこんなことがこんだけできたけど、お前はできないんだったら、変更しておけよ!」
って叱られそうです。
その点、protocolは準拠させるときに具体的に要件を設定すればいいので、
「出来そうなことを書いとくから、後はどんなふうにどれだけできるかはその都度設定してね!」
みたいな軽い感じがします。
さらに、protocolは型として認識されるので、funcの引数に設定できます。例えば、
protocol PersonProtocol {
var name: String {get set}
}
//protocol PersonProtocol に準拠したprotocol AdultPersonProtocolを定義します
protocol AdultPersonProtocol: PersonProtocol {
var job: String {get set}
}
//protocol PersonProtocol に準拠したstruct PersonAを定義します
struct PersonA: PersonProtocol {
var name: String
init(){
name = ""
}
}
//protocol AdultPersonProtocolに準拠したstruct PersonBを定義します
struct PersonB: AdultPersonProtocol {
var name: String
var job: String
init(){
name = ""
job = ""
}
}
//struct PersonAを実装したpersonAを定義します
var personA = PersonA()
personA.name = "子供店長"
//struct PersonBを実装したpersonBを定義します
var personB = PersonB()
personB.name = "大人店長"
personB.job = "サラリーマン"
//ここでprotocol PersonProtocolをfuncの引数personの型に設定します
func printName(_ person: PersonProtocol) {
//protocol PersonProtocolのプロパティnameに設定された値を表示します
print(person.name)
}
printName(personA)
//子供店長
printName(personB)
//大人店長
こんな感じです。protocolのAdultPersonProtocolはPersonProtocolに準拠しているので、PersonProtocol型でもあります。ですから、この場合の引数として有効です。