由于在Swift中元组不可散列,所以我创建了一个通用结构体Couple,包含两个元素,这些元素组合在一起可以用作字典的键。
struct Couple<U: Hashable, V: Hashable>: Hashable {
let u: U
let v: V
init( _ u: U, _ v: V ) {
self.u = u
self.v = v
}
}
var dictionary: [ Couple<Int,Int> : Any ] = ...
现在,我想通用地使用Couple扩展Dictionary。
extension Dictionary where Key == Couple<U: Hashable, V: Hashable>, Value == Any {
func exampleConvertToArray() -> [ ( U, V, Any ) ] {
}
}
无论我如何在扩展语句中引用Couple,U,V,编译器都会抱怨。如果我改为将泛型添加到函数定义中,编译器也会抱怨。
如果类型不是通用类型(extension Dictionary where Key == Couple<Int, Int>, Value == Any
,则一切正常。
如何创建此通用扩展名?
实现此目的的一种方法是定义您的Couple
类型符合的协议,然后让您的扩展名应用于其键符合该协议的字典,例如:
protocol CoupleProtocol {
associatedtype U
associatedtype V
var u: U { get }
var v: V { get }
}
struct Couple<U, V>: CoupleProtocol, Hashable where U: Hashable, V: Hashable {
let u: U
let v: V
init(_ u: U, _ v: V) {
self.u = u
self.v = v
}
}
extension Dictionary where Key: CoupleProtocol {
func exampleConvertToArray() -> [(Key.U, Key.V, Any)] {
return map { ($0.u, $0.v, $1) }
}
}
let dictionary: [Couple<Int, Int>: Any] = [
Couple(1, 2): [1, 2],
Couple(3, 4): "(3, 4)",
Couple(5, 6): (5, 6)
]
let array = dictionary.exampleConvertToArray() // array is of type: [(Int, Int, Any)]
print(array) // prints: [(3, 4, "(3, 4)"), (1, 2, [1, 2]), (5, 6, (5, 6))]
这是可能的,但是不幸的是,通用约束必须在成员本身而不是整个extension
上表达:
struct Couple<U: Hashable, V: Hashable>: Hashable {
let u: U
let v: V
init( _ u: U, _ v: V ) {
self.u = u
self.v = v
}
}
extension Dictionary {
func exampleConvertToArray<U, V>() -> [(U, V, Any)] where Key == Couple<U, V> {
self.map { (key, value) in (key.u, key.v, value) }
}
}
let input = [
Couple(1, 2): 3,
Couple(4, 5): 6,
Couple(7, 8): 9,
]
let result = input.exampleConvertToArray()
print(result)