协议和扩展

优质
小牛编辑
127浏览
2023-12-01

协议和扩展

  • 你可以扩展一个已经存在的类型来采纳和遵循一个新协议, 就算是你无法访问现有类型的源代码也行. 扩展可以添加新的属性、方法和下标到已经存在的类型, 并且因此允许你添加协议需要的任何需要.
protocol TextRepresentable {
    var textualDescription: String { get }
}

// 此处并无Dice这个类, 以及其sides属性
extension Dice: TextRepresentable {
    var textualDescription: String  {
        "A \(sides)- sided dice"
    }
}

有条件的遵循协议

  • 泛型类型可能只在某些情况下满足一个协议的要求, 比如当类型的泛型形式参数遵循对应协议时. 你可以通过在扩展类型时列出限制让泛型类型有条件的遵循某协议. 在你采纳协议的名字后面写泛型where分句.
protocol TextRepresentable {
    var textualDescription: String { get }
}
extension Array: TextRepresentable where Element: TextRepresentable {
    var textualDescription: String {
        let itemsAsText = self.map { $0.textualDescription }
        return "[" + itemsAsText.joined(separator: ",") + "]"
    }
}
extension Collection where Iterator.Element: TextRepresentable {
    var textualDescription: String {
        let itemsAsText = self.map { $0.textualDescription }
        return "[" + itemsAsText.joined(separator: ",") + "]"
    }
}

使用扩展声明采纳协议

  • 如果一个类型已经遵循了协议的所有要求, 但是还没有声明它采纳了这个协议, 你可以通过一个空的扩展来让它采纳这个协议.
protocol TextRepresentable {
    var textualDescription: String { get }
}

struct Hamster {
    var name: String
    var textualDescription: String {
        return "A hamster named \(name)"
    }
}
extension Hamster: TextRepresentable {}

协议扩展

  • 协议可以通过扩展来提供方法和属性的实现以遵循类型. 这就允许你在协议自身定义行为, 而不是在每一个遵循或者全局函数里定义.
struct LinearCongruentialGenerator: RandomNumberGenerator {
    func random() -> Double {
        return 8.0
    }
}

protocol RandomNumberGenerator {
    func random() -> Double
}

extension RandomNumberGenerator {
    func randomBool() -> Bool {
        return random() > 0.5
    }
}

let generator = LinearCongruentialGenerator()
print("Here's a random number: \(generator.random())")
print("And here's a random Boolean: \(generator.randomBool())")

输出结果:

Here's a random number: 8.0
And here's a random Boolean: true

提供默认实现

  • 你可以使用协议扩展来给协议的任意方法或者计算属性要求提供默认实现. 如果遵循类型给这个协议的要求提供了它自己的实现, 那么它就会替代扩展中提供的默认实现.