1

(随时酌情重命名问题)

我正在处理大量 BLE 数据,出于调试目的,我发现UInt8使用HEX计算变量进行扩展很容易:

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
    }
}

然后是我想利用这一点并提供HEXandhex方法的默认实现的部分:

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'

我想我明白这一点。也就是说,作为一个协议,它不能保证采用的类型是CVarArgType可以在 String 初始化器中使用的类型 ( ) 。所以我想我可以where第一次使用子句。我修改了我的协议扩展,如下所示:

extension HexPrintable where Self == CVarArgType { ...

这导致Same-type requirement makes generic parameter 'Self' non-generic. 在这一点上,我的业余类型理论家的理解溢出了。使我在不同 UInt 大小上的两种扩展方法起作用的魔力是什么?

4

1 回答 1

1

正确的语法是

extension HexPrintable where Self : CVarArgType { ... }

或者,使您的HexPrintable协议继承自CVarArgType

protocol HexPrintable : CVarArgType {
    var hexDigitCount:Int { get }
}

请注意,您可以使用单个扩展 on 实现相同的功能IntegerTypesizeofValue() 用于确定输出宽度:

extension IntegerType where Self : CVarArgType {
    var HEX : String {
        let size = sizeofValue(self)
        return String(format: "%0\(2*size)X", self)
    }
}

但是还有一个问题:%X格式需要一个Int32参数(对应于Cint类型)。对于超出 32 位整数范围的值,您和我的上述代码都不会产生正确的结果。

例如在 如何为所有整数类型创建通用整数到十六进制函数?(我刚刚添加了另一个)。

于 2015-10-22T19:08:36.520 回答