未能实现符合类型的协议扩展
Failing to implement Protocol Extension for conforming type
(请酌情重新命名问题)
我正在处理大量 BLE 数据,出于调试目的,我发现使用 HEX
计算变量很容易扩展 UInt8
:
extension UInt8 {
var HEX:String {
return String(format: "%02X", self)
}
}
// 190.HEX --> "BE"
我发现自己想要一个小写的变体。然后我也想要 UInt32
和 UInt16
。由于唯一改变的是要打印的位数,我想我可以通过某种协议来做到这一点(至少出于教育目的)。
protocol HexPrintable {
var hexDigitCount:Int { get }
}
extension UInt8:HexPrintable {
var hexDigitCount:Int {
return 2
}
}
extension UInt16:HexPrintable {
var hexDigitCount:Int {
return 4
}
}
extension UInt32:HexPrintable {
var hexDigitCount:Int {
return 8
}
}
然后是我想利用它并提供 HEX
和 hex
方法的默认实现的部分:
extension HexPrintable {
var HEX:String {
return String(format: "%0\(self.hexDigitCount)X", self)
}
var hex:String {
return String(format: "%0\(self.hexDigitCount)x", self)
}
}
我收到编译器错误 Argument type 'Self' does not conform to expected type 'CVarArgType'
。
我想我明白了。它是说作为一个协议,它不能保证采用的类型是可以在 String 初始值设定项中使用的类型 (CVarArgType
)。所以我想我可以第一次使用 where
子句。我将协议扩展修改为:
extension HexPrintable where Self == CVarArgType { ...
这导致 Same-type requirement makes generic parameter 'Self' non-generic
。在这一点上,我的业余类型理论家的理解溢出了。是什么让我的两个扩展方法在不同的 UInt 大小上起作用?
正确的语法是
extension HexPrintable where Self : CVarArgType { ... }
或者,使您的 HexPrintable
协议继承自 CVarArgType
:
protocol HexPrintable : CVarArgType {
var hexDigitCount:Int { get }
}
请注意,您可以实现相同的功能
在 IntegerType
上使用单个扩展名,使用 sizeofValue()
确定输出宽度:
extension IntegerType where Self : CVarArgType {
var HEX : String {
let size = sizeofValue(self)
return String(format: "%0\(2*size)X", self)
}
}
但还有另一个问题:%X
格式需要一个 Int32
参数
(对应Cint
类型)。你和我上面的代码都会
对于超过 32 位范围的值,不会产生正确的结果
整数。
给出了该问题的各种可能解决方案,例如在
How to create a generic integer-to-hex function for all Integer types?(我刚刚添加了另一个
一个)。
(请酌情重新命名问题)
我正在处理大量 BLE 数据,出于调试目的,我发现使用 HEX
计算变量很容易扩展 UInt8
:
extension UInt8 {
var HEX:String {
return String(format: "%02X", self)
}
}
// 190.HEX --> "BE"
我发现自己想要一个小写的变体。然后我也想要 UInt32
和 UInt16
。由于唯一改变的是要打印的位数,我想我可以通过某种协议来做到这一点(至少出于教育目的)。
protocol HexPrintable {
var hexDigitCount:Int { get }
}
extension UInt8:HexPrintable {
var hexDigitCount:Int {
return 2
}
}
extension UInt16:HexPrintable {
var hexDigitCount:Int {
return 4
}
}
extension UInt32:HexPrintable {
var hexDigitCount:Int {
return 8
}
}
然后是我想利用它并提供 HEX
和 hex
方法的默认实现的部分:
extension HexPrintable {
var HEX:String {
return String(format: "%0\(self.hexDigitCount)X", self)
}
var hex:String {
return String(format: "%0\(self.hexDigitCount)x", self)
}
}
我收到编译器错误 Argument type 'Self' does not conform to expected type 'CVarArgType'
。
我想我明白了。它是说作为一个协议,它不能保证采用的类型是可以在 String 初始值设定项中使用的类型 (CVarArgType
)。所以我想我可以第一次使用 where
子句。我将协议扩展修改为:
extension HexPrintable where Self == CVarArgType { ...
这导致 Same-type requirement makes generic parameter 'Self' non-generic
。在这一点上,我的业余类型理论家的理解溢出了。是什么让我的两个扩展方法在不同的 UInt 大小上起作用?
正确的语法是
extension HexPrintable where Self : CVarArgType { ... }
或者,使您的 HexPrintable
协议继承自 CVarArgType
:
protocol HexPrintable : CVarArgType {
var hexDigitCount:Int { get }
}
请注意,您可以实现相同的功能
在 IntegerType
上使用单个扩展名,使用 sizeofValue()
确定输出宽度:
extension IntegerType where Self : CVarArgType {
var HEX : String {
let size = sizeofValue(self)
return String(format: "%0\(2*size)X", self)
}
}
但还有另一个问题:%X
格式需要一个 Int32
参数
(对应Cint
类型)。你和我上面的代码都会
对于超过 32 位范围的值,不会产生正确的结果
整数。
给出了该问题的各种可能解决方案,例如在 How to create a generic integer-to-hex function for all Integer types?(我刚刚添加了另一个 一个)。