23.3. 方法要求

协议可以要求遵循协议的类型实现某些指定的实例方法或类方法。这些方法作为协议的一部分,像普通方法一样放在协议的定义中,但是不需要大括号和方法体。可以在协议中定义具有可变参数的方法,和普通方法的定义方式相同。但是,不支持为协议中的方法提供默认参数。

正如属性要求中所述,在协议中定义类方法的时候,总是使用 static 关键字作为前缀。即使在类实现时,类方法要求使用 classstatic 作为关键字前缀,前面的规则仍然适用:

protocol SomeProtocol {
    static func someTypeMethod()
}

下面的例子定义了一个只含有一个实例方法的协议

protocol RandomNumberGenerator {
    func random() -> Double
}

RandomNumberGenerator 协议要求遵循协议的类型必须拥有一个名为 random, 返回值类型为 Double 的实例方法。尽管这里并未指明,但是我们假设返回值是从 0.0 到(但不包括)1.0

RandomNumberGenerator 协议并不关心每一个随机数是怎样生成的,它只要求必须提供一个随机数生成器。

如下所示,下边是一个遵循并符合 RandomNumberGenerator 协议的类。该类实现了一个叫做 线性同余生成器(linear congruential generator) 的伪随机数算法。

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))
        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”