2015-10-22 2 views
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 
    } 
} 

Затем идет часть, где я хочу воспользоваться этим и обеспечить реализацию по умолчанию в 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'.

Думаю, я это понимаю. Он говорит, что в качестве протокола он не может гарантировать, что принятые типы будут иметь тип (CVarArgType), который может быть использован в инициализаторе String. Поэтому я думал, что могу использовать предложение where в первый раз. Я изменил свое расширение протокола выглядеть следующим образом:

extension HexPrintable where Self == CVarArgType { ... 

что приводит к Same-type requirement makes generic parameter 'Self' non-generic. В этот момент понимание моего теоретика теоретического типа переполнилось. Какая магия позволяет использовать мои два метода расширения для разных размеров UInt?

ответ

1

Правильный синтаксис будет

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 аргумент (соответствующий типу С int). Как ваш, так и мой код выше не дают правильных результатов для значений, превышающих диапазон 32-разрядного целого числа .

Даны различные возможные решения этой проблемы. в How to create a generic integer-to-hex function for all Integer types? (и я просто добавил еще один ).

+0

Прохладный. Это, конечно, проще, чем то, что я пытался. Было ли то, что я пытался даже технически возможно? Я хотел бы понять ошибки, которые я видел лучше ... –

+0

@TravisGriggs: См. Обновление. –

+0

Ahh ... так что это был только бит '=='. Является ли '==' в предложении where фактически законным синтаксисом, что означает что-то еще? –

Смежные вопросы