Pure swift set with protocol objects

One solution is to wrap the set in a class or structure, and constrain the insertion function so that it only accepts items that conform to your protocol and to hashable. You can then use a Set of AnyHashable in the implementation.

For example:

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()
    }
}

By putting the constraints on the insertion function, you're saying "this set has to contain things that conform to the protocol, and are hashable", without actually constraining the protocol to being hashable.

It would be even nicer if the wrapping set class could itself be generic, and take in the protocol to conform to, but I haven't figured out if that is possible yet!


Perhaps there is a better solution, but you can make your class generic:

protocol testProtocol : Hashable {
    //
}

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

    init() { }
}