0

我想扩展 UInt8 值的数组,所以我在Swift 3中编写了这段代码:

extension Array where Element: UInt8  {

}

但我得到了这个错误:

类型 'Self.Generator.Element' 约束为非协议类型 'UInt8'

那么我该如何解决呢?

4

1 回答 1

3

语法Element: X意味着您要对Element由 定义的类型约束X,其中X必须Element是派生的协议或类。作为一种解决方法,如果您想构建一个Array仅适用于具有 (value type) element 的数组的扩展UInt8,您可以定义一个仅UInt8符合的协议,并将此协议用作扩展中的类型约束。例如

protocol MyType {}
extension UInt8: MyType {}

extension Array where Element: MyType  {
    // ...
}

在其当前实现中,扩展中的任何代码对Element类型的了解都比协议中的蓝图多MyType(即,目前,一无所知)。根据您希望通过扩展实现的目标,您可以将蓝图添加到MyType您知道已经由可用的实现实现的蓝图UInt8,例如一些初始化程序。但更明智的做法是利用UInt8符合有用协议的事实UnsignedIntegerEquatable并且Comparable. 通过使用协议组合,这些协议蓝图的所有方法都可以很容易地用于Element扩展中的 :s ,但是将这些元素限制为符合您自己的协议的类型MyType(即,仅UInt8):

protocol MyType {}
extension UInt8: MyType {}

extension Array where Element: MyType & UnsignedInteger {
    mutating func superfluouslyReplaceAllElements(with value: Element) {
        self = self.map { $0.advanced(by: $0.distance(to: value)) }
    } /* using 'advanced(by:)' and 'distance(to:)' methods of
         'Element', blueprinted in 'UnsignedInteger', to which 
         'Element' conforms */

    mutating func elementsSquaredWithOverflow() -> Bool {
        var overflow = false
        self = self.map {
            let result = Element.multiplyWithOverflow($0, $0)
            overflow = overflow || result.overflow
            return result.0
        }
        return overflow // did at least one element cause an arithmetic overflow?
    }
}

var foo: [UInt8] = [14, 87, 13, 240]
print(foo.elementsSquaredWithOverflow()) // true (at least one arithmetic overflow)
print(foo) // [196, 145, 169, 0]

foo.superfluouslyReplaceAllElements(with: 42)
print(foo) // 42, 42, 42, 42

var bar: [UInt16] = [14, 87, 13, 240]
bar.superfluouslyReplaceAllElements(with: 42)
    /* error: type 'UInt16' does not conform to protocol 'MyType' 
       OK, as expected!                                           */

然而,这只是协议和类型约束的简短课程;如果您打算UInt8在字节上下文中使用序列,请遵循@vadian:s 在他对您问题的评论中的建议。

于 2016-11-20T12:22:53.953 回答