使用协议对象进行纯粹快速设置

时间:2015-03-26 12:37:19

标签: swift set protocols

有没有办法让以下内容真正起作用?

V1 - “测试协议不符合Hashable”

protocol testProtocol  {
    //
}

class test {
    var s : Set<testProtocol>?
    init(){
    }
}

V2 - “协议'testProtocol'只能用作通用约束,因为它具有Self或相关类型要求

protocol testProtocol : Hashable {
    //
}

class test {
    var s : Set<testProtocol>?
    init(){
    }
}

我假设答案是否定的 - 因为协议(即使使用@objc标签)没有足够的信息?但也许我在这里缺少某种线条或东西。

3 个答案:

答案 0 :(得分:3)

也许有一个更好的解决方案,但你可以让你的类通用:

protocol testProtocol : Hashable {
    //
}

class test<P: testProtocol> {
    var s : Set<P>?

    init() { }
}

答案 1 :(得分:1)

一种解决方案是将集合包装在类或结构中,并限制插入函数,以便它仅接受符合协议且可哈希的项。然后,您可以在实现中使用Set中的AnyHashable

例如:

protocol MyProtocol {
    func doStuff()
}

class MyProtocolSet {
    var set = Set<AnyHashable>()

    func insert<T>(_ item: T) where T: MyProtocol, T: Hashable {
        set.insert(AnyHashable(item))
    }

    func iterate( doing: (MyProtocol) -> Void ) {
        for item in set {
            doing(item as! MyProtocol)
        }
    }
}

struct Foo: MyProtocol, Hashable {
    func doStuff() { print("foo") }
}

struct Bar: MyProtocol, Hashable {
    func doStuff() { print("bar") }
}

func test() {
    let set = MyProtocolSet()
    set.insert(Foo())
    set.insert(Bar())
    set.iterate { (item: MyProtocol) in
        item.doStuff()
    }
}

通过对插入函数施加约束,您说的是“此集合必须包含符合协议且可以哈希的内容”,而实际上并没有将协议限制为可哈希的。

如果包装集类本身可以是通用的,并接受要符合的协议,那就更好了,但是我还没有弄清楚这是否可行!

答案 2 :(得分:1)

我知道这不是Set(就像询问的问题一样),但是您可以使用NSHashTable代替Set。但是,您必须将协议公开给objc。尽管不是Set,但如果您只是想存储协议对象的集合而不必遵守Hashable,则可以使用:

@objc protocol testProtocol { }
class Object {
    var s: NSHashTable<testProtocol>!
}

这样,您就可以使用提供的addremove函数。

此外,如果要存储观察者或类似对象,则可以使用NSHashTable.weakObjects()初始化哈希表,以确保不保留对象。

关于NSHashTable的更多信息:https://developer.apple.com/documentation/foundation/nshashtable