版本
Xcode 11.3.1
Swift 5.1.3
協議
協議規定了用來實現某一特定功能所必需的方法和屬性。
類,結構體或枚舉類型都可以遵循協議,並提供具體實現來完成協議定義的方法和功能。
語法
protocol SomeProtocol {
// 這裏是協議的定義部分
}
讓自定義類型遵循多個協議:
struct SomeStructure: FirstProtocol, AnotherProtocol {
// 這裏是結構體的定義部分
}
若是一個類擁有父類,應該將父類名放在遵循的協議名之前,以逗號分隔:
class SomeClass: SomeSuperClass, FirstProtocol, AnotherProtocol {
// 這裏是類的定義部分
}
屬性要求
協議不指定屬性是存儲屬性還是計算屬性,它只指定屬性的名稱和類型。
此外,協議還指定屬性是可讀的還是可讀可寫的。
如果協議規定可讀可寫,那麼協議的實現也是可讀可寫的;如果協議規定可讀,實現除了可讀外,也可根據實際需要是否可寫。
在類型聲明後加上 { set get } 來表示屬性是可讀可寫的,用 { get } 來表示只讀。
protocol Subject {
var name: String { get }
var score: Int { get set }
}
struct Math: Subject {
var name: String { return "Math" }
var score = 0
}
var math = Math()
//math.name = "Chinese" // 只讀屬性,報錯
math.score = 100
print(math.name, math.score)
// 打印 Math 100
方法要求
協議可以要求遵循協議的類型實現某些指定的實例方法或類方法。
protocol SayHello {
func sayHello()
}
class Person: SayHello {
var name: String
init(name: String) {
self.name = name
}
func sayHello() {
print("\(self.name) say hello")
}
}
let xiaoming = Person(name: "小明")
xiaoming.sayHello()
// 小明 say hello
let xiaohong = Person(name: "小紅")
xiaohong.sayHello()
// 小紅 say hello
構造器要求
你可以在遵循協議的類中實現構造器,無論是作爲指定構造器還是作爲便利構造器,你都必須爲構造器實現標上 required 修飾符:
protocol SayHello {
func sayHello()
}
class Person: SayHello {
var name: String
init(name: String) {
self.name = name
}
func sayHello() {
print("\(self.name) say hello")
}
}
let xiaoming = Person(name: "小明")
xiaoming.sayHello()
// 小明 say hello
let xiaohong = Person(name: "小紅")
xiaohong.sayHello()
// 小紅 say hello
protocol StudentName {
init(studentName: String)
}
class Student: Person, StudentName {
required init(studentName: String) {
super.init(name: studentName)
}
}
let xiaojun = Student(studentName: "學生小軍")
xiaojun.sayHello()
// 學生小軍 say hello
委託
委託是一種設計模式,它允許類或結構體將一些需要它們負責的功能委託給其他類型的實例。
舉個例子:
// 定義一個看門的協議
protocol WatchDoor {
func watchDoor()
}
// 人類會看門,所以遵循 WatchDoor 協議
class People: WatchDoor {
var name: String
init(name: String) {
self.name = name
}
func watchDoor() {
print("\(self.name)看門")
}
// 定義一個被委託對象,來代理看門任務 (現在這個被委託對象是誰還不知道)
var delegate: WatchDoor? = nil
}
// 打南面來了一條狗
class Dog {
var name: String
init(name: String) {
self.name = name
}
}
// 某天這狗的任督二脈被打通,從此具備看門的能力
extension Dog: WatchDoor {
func watchDoor() {
print("\(self.name)看門")
}
}
// 本來是人類小康看門
let people = People(name: "小康")
people.watchDoor()
// 看到狗兒旺財來了
let dog = Dog(name: "旺財")
// 然後委託旺財來看門
people.delegate = dog
// 現在是旺財在看門
people.delegate?.watchDoor()
/**
小康看門
旺財看門
*/