swift - 一次扩展多个协议
问题描述
我想为多个协议编写扩展,发现这篇文章非常有趣,但我无法完全遵循 Matthew Seaman。
在这种情况下,我想写我自己的extension BinaryNumber
,我想添加到BinaryInteger
和BinaryFloatingPoint
. 但是当我尝试添加我的协议时,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
解决方案
一般来说,不可能在多个协议上编写单个扩展。这将要求编译器找出所有这些协议中所有成员的集合交集(这些是您在扩展中可以访问的成员),而编译器无法做到这一点。
为避免代码重复,您需要计算出您需要的成员 - 在您的情况下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 & ExpressibleByIntegerLiteral
then 的扩展,因为它们提供了我们正在使用的所有成员?好吧,因为那不是标称类型,而且您不能在非标称类型上编写扩展:(
但是,您可以这样写:
// now you don't need your own "BinaryNumbers"!
extension Comparable where Self: ExpressibleByIntegerLiteral {
func atMost127() -> Bool {
self <= 127
}
}
您只能这样做,因为您需要的两个成员都来自协议。如果出于某种原因,您需要一个既具有BinaryFloatingPoint
又BinaryInteger
具有但不由它们所遵循的任何协议提供的成员,那么您需要使用这些成员编写自己的协议,并手动使所有内容都符合该协议。
推荐阅读
- c# - 如何正确绑定 XAML 中的 ObservableCollection?
- powershell - Powershell 从对象中选择 NoteProperty 类型对象
- swift - Swift - 如何访问单元格名称
- python - 为什么 system("cls") 在 Python 中无法正常工作,因为它编写了一些奇怪的箭头字符?
- vector - Rust - 如何从函数返回多个变量,以便在调用函数的范围之外可以访问它们?
- python - 位置 args 元组的索引 1 超出范围
- julia - 如何用 Julia 绘制球体?
- rust - HashMap 的 split_at_mut 等价物?
- php - Laravel 关系将列组合到逗号分隔的字符串
- html - 应用时无法获得所需的字体样式