Swift 扩展 UInt8 数组
Swift extend UInt8 Array
我想扩展一个 UInt8 值数组,所以我在 Swift 3:
中编写了这段代码
extension Array where Element: UInt8 {
}
但是我得到了这个错误:
类型'Self.Generator.Element' 约束为非协议类型'UInt8'
那我该如何解决呢?
语法 Element: X
表示您要对 X
定义的 Element
施加类型约束,其中 X
必须是协议或 class 从中导出 Element
。作为解决方法,如果您想构建 Array
的扩展,它只适用于具有(值类型)元素 UInt8
的数组,您可以定义一个协议,只有 UInt8
符合,并使用此协议作为扩展中的类型约束。例如
protocol MyType {}
extension UInt8: MyType {}
extension Array where Element: MyType {
// ...
}
在当前的实现中,扩展中的任何代码对 Element
类型的了解仅比 MyType
协议中的蓝图更多(即,目前,一无所知)。根据您希望通过扩展实现的目标,您可以将蓝图添加到 MyType
,您知道这些蓝图已经由 UInt8
可用的实现实现,例如一些初始化程序。但更明智的方法是利用 UInt8
符合有用协议 UnsignedInteger
、Equatable
和 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 { [=11=].advanced(by: [=11=].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([=11=], [=11=])
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 在他对您的问题的评论中的建议。
我想扩展一个 UInt8 值数组,所以我在 Swift 3:
中编写了这段代码extension Array where Element: UInt8 {
}
但是我得到了这个错误:
类型'Self.Generator.Element' 约束为非协议类型'UInt8'
那我该如何解决呢?
语法 Element: X
表示您要对 X
定义的 Element
施加类型约束,其中 X
必须是协议或 class 从中导出 Element
。作为解决方法,如果您想构建 Array
的扩展,它只适用于具有(值类型)元素 UInt8
的数组,您可以定义一个协议,只有 UInt8
符合,并使用此协议作为扩展中的类型约束。例如
protocol MyType {}
extension UInt8: MyType {}
extension Array where Element: MyType {
// ...
}
在当前的实现中,扩展中的任何代码对 Element
类型的了解仅比 MyType
协议中的蓝图更多(即,目前,一无所知)。根据您希望通过扩展实现的目标,您可以将蓝图添加到 MyType
,您知道这些蓝图已经由 UInt8
可用的实现实现,例如一些初始化程序。但更明智的方法是利用 UInt8
符合有用协议 UnsignedInteger
、Equatable
和 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 { [=11=].advanced(by: [=11=].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([=11=], [=11=])
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 在他对您的问题的评论中的建议。