协议定义
协议规定了用来实现某一特定任务或者功能的方法、属性,以及其他需要的东西。类、结构体或枚举都可以遵循协议,并为协议定义的这些要求提供具体实现。
协议语法
protocol SomeProtocol {
// 这里是协议的定义部分
}
遵循协议语法
结构体: 协议1, 协议2
struct SomeStructure: FirstProtocol, AnotherProtocol {
// 这里是结构体的定义部分
}
类:父类, 协议1, 协议2
class SomeClass: SomeSuperClass, FirstProtocol, AnotherProtocol {
// 这里是类的定义部分
}
属性要求
协议可以要求遵循协议的类型提供特定名称和类型的实例属性或类型属性。协议不指定属性是存储属性还是计算属性,它只指定属性的名称和类型。此外,协议还指定属性是可读的还是可读可写的
如果协议要求属性是可读可写的,那么该属性不能是常量属性或只读的计算型属性。如果协议只要求属性是可读的,那么该属性不仅可以是可读的,如果代码需要的话,还可以是可写的
协议实例属性的声明
protocol SomeProtocol {
var mustBeSettable: Int { get set } //类型声明后加上 { set get } 来表示属性是可读可写
var doesNotNeedToBeSettable: Int { get } 可读属性
}
协议类型属性的声明
protocol AnotherProtocol {
static var someTypeProperty: Int { get set }
//定义类型属性 使用 static 或 class 关键字作为前缀
}
protocol FullyNamed {
var fullName: String { get }
}
协议使用遵循 FullyNamed
协议的简单结构体。
struct Person: FullyNamed {
var fullName: String
}
let john = Person(fullName: "John Appleseed")
// john.fullName 为 "John Appleseed"
使用2: 协议属性被用作于计算属性
class Starship: FullyNamed {
var prefix: String?
var name: String
init(name: String, prefix: String? = nil) {
self.name = name
self.prefix = prefix
}
var fullName: String {
return (prefix != nil ? prefix! + " " : "") + name
}
}
var ncc1701 = Starship(name: "Enterprise", prefix: "USS")
// ncc1701.fullName 为 "USS Enterprise"
方法要求
协议可以要求遵循协议的类型实现某些指定的实例方法或类方法。不支持为协议中的方法提供默认参数。
类方法的时候,总是使用 static
关键字作为前缀。即使在类实现时,类方法要求使用 class
或 static
作为关键字前缀
类方法协议定义
protocol SomeProtocol {
static func someTypeMethod() //类方法用static或class 关键字作前缀
}
实例方法的协议:
protocol RandomNumberGenerator {
func random() -> Double
}
使用示例
class LinearCongruentialGenerator: RandomNumberGenerator {
var lastRandom = 42.0
let m = 139968.0
let a = 3877.0
let c = 29573.0
func random() -> Double {
lastRandom = ((lastRandom * a + c).truncatingRemainder(dividingBy:m))
// truncatingRemainder 浮点数取余方法,swift3之后使用
return lastRandom / m
}
}
let generator = LinearCongruentialGenerator()
print("Here's a random number: \(generator.random())")
// 打印 “Here's a random number: 0.37464991998171”
print("And another one: \(generator.random())")
// 打印 “And another one: 0.729023776863283”
异变方法协议要求(mutating 关键字)
mutating
关键字作为方法的前缀,写在 func
关键字之前,表示可以在该方法中修改它所属的实例以及实例的任意属性