IT工房くまや

通称くまが運営するIT工房サイト

Swiftのprotocolについて調べてみました

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型でもあります。ですから、この場合の引数として有効です。