- 协议可以用来定义方法、属性、下标的声明,协议可以被枚举、结构体、类遵守(多个协议之间用逗号隔开)
protocal Drawable {
func draw()
var x: Int { get set }
var y: Int { get }
subscript(index: Int) -> Int { get set }
}
- 协议中定义方法时不能有默认参数值
- 默认情况下,协议中定义的内容必须全部都实现
协议中的property
- 协议中定义属性时必须用var关键字
- 实现协议时的属性权限要不小于协议中定义的属性权限
协议定义get、set,用var存储属性或get、set计算属性去实现
协议定义get,用任何属性都可以实现
协议中的static、class、mutating
- 为了保证通用,协议中必须用static定义类型方法、类型属性、类型下标
协议中的mutating
- 只有将协议中的实例方法标记为mutating
才允许结构体、枚举的具体实现修改自身内存
类在实现方法时不用加mutating,枚举、结构体才需要加mutating
协议中的init、init?、init!
- 协议中还可以定义初始化器init
非final类实现时必须加上required
- 如果从协议实现的初始化器,刚好是重写了父类的指定初始化器
那么这个初始化必须同时加上required、override
- 协议中定义了init?、init!,可以用init、init?、init!去实现
- 协议中定义的init,可以用init、init!去实现
协议中的inheritance
- 一个协议可以继承其他协议
协议组合
- 协议组合,可以包含一个类类型(最多一个)
protocol Liveable {}
protocol Runnalbe {}
class Person {}
func fn0(objc: Person) {}
func fn1(objc: Liveable) {}
func fn2(objc: Liveable & Runnable) {}
func fn3(objc: Person & Liveable & Runnable) {}
typealias RealPerson = Person & Liveable & Runnable
func fn4(obj: RealPerson){}
协议CaseIterable
- 让枚举遵守CaseIterable协议,可以实现遍历枚举值
enum Season : CaseIterable {
case spring, summer, autumn, winter
}
let seasons = Season.allCases
print(seasons.count) //4
for season in seasons {
print(season)
} //spring summer autumn winter
协议CustomStringConvertible、CustomDebugStringConvertible
- 遵守CustomStringConvertible协议、CustomDebugStringConvertible协议,都可以自定义实例的打印字符串
class Person : CustomStringConvertible, CustomDebugStringConvertible {
var age: Int
var name: String
init(age: Int, name: String) {
self.age = age
self.name = name
}
var description: String {
"age=\(age), name=\(name))"
}
var debugDescription: String {
"debug_age=\(age), debug_name=\(name))"
}
}
var p = Person(age: 10, name: "Jack")
print(p) // age=10, name=Jack
debugPrint(p) // debug_age=10, debug_name=Jack