首页 > 解决方案 > 一次扩展多个协议

问题描述

我想为多个协议编写扩展,发现这篇文章非常有趣,但我无法完全遵循 Matthew Seaman。

在这种情况下,我想写我自己的extension BinaryNumber,我想添加到BinaryIntegerBinaryFloatingPoint. 但是当我尝试添加我的协议时,Xcode 会显示错误消息Extension of protocol 'BinaryInteger' (or 'BinaryFloatingPoint') cannot have an inheritance Clause 。

这是我的代码:

protocol BinaryNumbers {} // my protocol

extension BinaryNumbers {
    func foo() -> Void {
        print("It works!")
    }
}

// try to extend Swift protocols
extension BinaryInteger : BinaryNumbers {} // doesn't work
extension BinaryFloatingPoint : BinaryNumbers {} // doesn't work

//更新

@sweeper 建议扩展Numeric,所以我尝试了,但出现错误。

extension Numeric {
    func foo() -> Bool {
        return self <= 127
        // Referencing operator function '<=' on 'BinaryInteger' requires
        // that 'Self' conform to 'BinaryInteger'
    }
}

当我一一扩展时BinaryInteger,它就起作用了。BinaryFloatingPoint

标签: swift

解决方案


一般来说,不可能在多个协议上编写单个扩展。这将要求编译器找出所有这些协议中所有成员的集合交集(这些是您在扩展中可以访问的成员),而编译器无法做到这一点。

为避免代码重复,您需要计算出您需要的成员 - 在您的情况下init(integerLiteral:)<=将它们放入您自己的协议中,并使您希望扩展应用到的具体类型符合您自己的协议:

// inheriting from Comparable and ExpressibleByIntegerLiteral gives you the members you need
protocol BinaryNumbers : Comparable & ExpressibleByIntegerLiteral {

}

extension BinaryNumbers {
    func atMost127() -> Bool {
        self <= 127
    }
}

extension Int: BinaryNumbers {}
extension Int8: BinaryNumbers {}
extension Int16: BinaryNumbers {}
extension Int32: BinaryNumbers {}
extension Int64: BinaryNumbers {}
// ... plus the unsigned versions, if you need them

extension Float16: BinaryNumbers {}
extension Float32: BinaryNumbers {}
extension Float64: BinaryNumbers {}
extension Float80: BinaryNumbers {}

现在你可能会问,我们为什么不做一个Comparable & ExpressibleByIntegerLiteralthen 的扩展,因为它们提供了我们正在使用的所有成员?好吧,因为那不是标称类型,而且您不能在非标称类型上编写扩展:(

但是,您可以这样写:

// now you don't need your own "BinaryNumbers"!
extension Comparable where Self: ExpressibleByIntegerLiteral {
    func atMost127() -> Bool {
        self <= 127
    }
}

您只能这样做,因为您需要的两个成员都来自协议。如果出于某种原因,您需要一个既具有BinaryFloatingPointBinaryInteger具有但不由它们所遵循的任何协议提供的成员,那么您需要使用这些成员编写自己的协议,并手动使所有内容都符合该协议。


推荐阅读