我想为多个协议编写扩展,发现 this posting 非常有趣,但我无法完全遵循 Matthew Seaman。
在这种情况下,我想编写自己的 extension BinaryNumber
,并将其添加到 BinaryInteger
和 BinaryFloatingPoint
。但是当我尝试添加我的协议时,Xcode 显示错误消息 Extension of protocol 'BinaryInteger'(或 'BinaryFloatingPoint')不能有继承子句。
这是我的代码:
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
时,它起作用了。
答案 0 :(得分:2)
一般来说,不可能在多个协议上编写单个扩展。这将要求编译器找出所有这些协议中所有成员的集合交集(那些是您在扩展中可以访问的成员),而编译器无法做到这一点。
为避免代码重复,您需要确定您需要的成员 - 在您的情况下 init(integerLiteral:)
和 <=
,将它们放入您自己的协议中,并使具体< /em> 您希望扩展适用的类型,符合您自己的协议:
// 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 & ExpressibleByIntegerLiteral
呢?好吧,因为那不是名义类型,而且你不能在非名义类型上写扩展:(
但是,你可以这样写:
// now you don't need your own "BinaryNumbers"!
extension Comparable where Self: ExpressibleByIntegerLiteral {
func atMost127() -> Bool {
self <= 127
}
}
您之所以能够这样做,是因为您需要的两个成员都来自协议。如果由于某种原因您需要一个 BinaryFloatingPoint
和 BinaryInteger
都有的成员,但它们所遵循的任何协议都没有提供,那么您需要为这些成员编写自己的协议,并且手动使所有内容都符合该协议。