協(xié)議能夠要求其遵循者必須含有一些特定名稱和類型的實(shí)例屬性(instance property)或類屬性 (type property),也能夠要求屬性具有(設(shè)置權(quán)限)settable 和(訪問權(quán)限)gettable,但它不要求屬性是存儲(chǔ)型屬性(stored property)還是計(jì)算型屬性(calculate property)。
如果協(xié)議要求屬性具有設(shè)置權(quán)限和訪問權(quán)限,那常量存儲(chǔ)型屬性或者只讀計(jì)算型屬性都無法滿足此要求。如果協(xié)議只要求屬性具有訪問權(quán)限,那任何類型的屬性都可以滿足此要求,無論這些屬性是否具有設(shè)置權(quán)限。
通常前置var關(guān)鍵字將屬性聲明為變量。在屬性聲明后寫上{ get set }表示屬性為可讀寫的。{ get }用來表示屬性為可讀的。即使你為可讀的屬性實(shí)現(xiàn)了setter方法,它也不會(huì)出錯(cuò)。
protocol SomeProtocol {
var musBeSettable : Int { get set }
var doesNotNeedToBeSettable: Int { get }
}
用類來實(shí)現(xiàn)協(xié)議時(shí),使用class關(guān)鍵字來表示該屬性為類成員;用結(jié)構(gòu)體或枚舉實(shí)現(xiàn)協(xié)議時(shí),則使用static關(guān)鍵字來表示:
protocol AnotherProtocol {
class var someTypeProperty: Int { get set }
}
protocol FullyNamed {
var fullName: String { get }
}
FullyNamed協(xié)議含有fullName屬性。因此其遵循者必須含有一個(gè)名為fullName,類型為String的可讀屬性。
struct Person: FullyNamed{
var fullName: String
}
let john = Person(fullName: "John Appleseed")
//john.fullName 為 "John Appleseed"
Person結(jié)構(gòu)體含有一個(gè)名為fullName的存儲(chǔ)型屬性,完整的遵循了協(xié)議。(若協(xié)議未被完整遵循,編譯時(shí)則會(huì)報(bào)錯(cuò))。
如下所示,Startship類遵循了FullyNamed協(xié)議:
class Starship: FullyNamed {
var prefix: String?
var name: String
init(name: String, prefix: String? = nil ) {
self.anme = name
self.prefix = prefix
}
var fullName: String {
return (prefix ? prefix ! + " " : " ") + name
}
}
var ncc1701 = Starship(name: "Enterprise", prefix: "USS")
// ncc1701.fullName == "USS Enterprise"
Starship類將fullName實(shí)現(xiàn)為可讀的計(jì)算型屬性。它的每一個(gè)實(shí)例都有一個(gè)名為name的必備屬性和一個(gè)名為prefix的可選屬性。 當(dāng)prefix存在時(shí),將prefix插入到name之前來為Starship構(gòu)建fullName。