未能为符合类型

时间:2015-10-22 18:58:26

标签: swift generics swift-extensions swift-protocols

(根据需要随意重新提问)

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

extension UInt8 {
    var HEX:String {
        return String(format: "%02X", self)
    }
}

// 190.HEX --> "BE"

我发现自己想要一个小写的变体。然后我想要它UInt32UInt16。由于唯一改变的是打印的位数,我想我可以用各种协议(至少用于教育目的)来做到这一点。

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

然后是我想要利用它的部分,并提供HEXhex方法的默认实现:

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大小上工作的神奇之处是什么?

1 个答案:

答案 0 :(得分:1)

正确的语法是

extension HexPrintable where Self : CVarArgType { ... }

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

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

请注意,您可以实现相同的功能 使用IntegerTypesizeofValue()上使用一个附加信息 确定输出宽度:

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

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

给出了该问题的各种可能的解决方案。在 How to create a generic integer-to-hex function for all Integer types?(我刚刚添加了另一个 一个)。