如何将集合的Swift扩展限制为通用类型?

问题描述 投票:1回答:2

由于在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,则一切正常。

如何创建此通用扩展名?

swift dictionary generics extension-methods
2个回答
0
投票

实现此目的的一种方法是定义您的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))]

0
投票

这是可能的,但是不幸的是,通用约束必须在成员本身而不是整个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)
© www.soinside.com 2019 - 2024. All rights reserved.