协议(Protocol)
- 使用 protocol 关键字来定义一个协议;
- 协议可以用来定义方法、属性、下标的声明;
- 协议可以被枚举、结构体,类遵守;
- 多个协议之间可以用逗号隔开;
protocol Behaviour {
func run()
var age: Int { set get }
var height: Int {get}
subscript(index: Int) -> Int { get set}
}
protocol Behaviour1 {}
protocol Behaviour2 {}
protocol Behaviour3 {}
class Animal: Behaviour1, Behaviour2, Behaviour3 {
}
- 协议中定义的方法不能有默认参数值;
- 协议中定义的内容,默认必须全部实现;
协议的属性
- 协议中定义的属性必须都为 var 属性,let 属性将会报错;
- 实现协议的属性权限,不小于协议中定义的属性权限;
- 如果定义了 get 属性,实现协议时,可以实现为 get 或 get & set的计算属性;
- 如果定义了 get & set 属性,那么只能实现为get & set 的计算属性;
static 、class
- 为了保证通用,协议中必须用static定义类型方法、类型属性、类型下标;
- 因为枚举和结构体不能用 class;
protocol Behaviour {
static var height: Int {get}
}
class Animal: Behaviour {
class var height: Int {
return 10
}
}
mutating
- 只有将协议中的 实例方法 标记为mutating;
- 才能允许结构体、枚举的具体实现修改自身的内存;
- 类在实现方法时不用加 mutating 关键字,枚举、结构体需要加mutating(swift5.1好像已经不用加了);
protocol Behaviour {
mutating func run()
}
struct Animal: Behaviour {
func run() {
}
}
init
- 协议还可以声明初始化方法 init;非 final 类实现该初始化器必须加 require 关键字,final 类实现该初始化器可以不加 require 关键字;
protocol Behaviour {
init(age: Int, name: String)
}
class Animal: Behaviour {
required init(age: Int, name: String) {
// ...
}
}
final class Person: Behaviour {
init(age: Int, name: String) {
// ...
}
}
- 假如实现的协议方法的初始化器,正是重写父类的指定初始化器,那么这个初始化器方法必须同时加 require 、 override 关键字;
- 协议中定义的 init?、init!,可以用 init、init?、init! 去实现;
- 协议中定义的 init,可以用 init、init! 去实现;
协议的继承
protocol Behaviour {
func run()
subscript(index: Int) -> Int {get}
}
protocol SubBehaviour: Behaviour {
func eat()
}
class Animal: SubBehaviour {
subscript(index: Int) -> Int {
return 10
}
func eat() {
//...
}
func run() {
//...
}
}
协议的组合
protocol Drawable {}
protocol Runnable {}
class Person {}
// 接收Person或其子类的实例
func test1(obj: Person) {}
// 接收遵守Drawable协议的实例
func test2(obj: Drawable) {}
// 接收遵守 Drawable与Runnable 协议的实例
func test3(obj: Drawable & Runnable) {}
// 接收遵守 Drawable与Runnable 协议,并且是Person或其子类的实例
func test4(obj: Person & Drawable & Runnable) {}
CaseIterable
- 让枚举遵守 CaseIterable 协议,可以实现枚举遍历;
enum Test : CaseIterable {
case a, b, c, d
}
let cases = Test.allCases
print(cases.count) // 4
for c in cases {
print(c)
} // a、b、c、d