You are hardly alone struggling with this, it seems to come up every other week!
You can write your own custom AnyProtocol type that includes Self, a pain but doable, e.g.: protocol A { func a() -> String } protocol B { func b() -> String } struct AB1: A, B, Hashable { func a() -> String { return "AB1.a" } func b() -> String { return "AB1.b" } var hashValue: Int { return 1 } static func ==(lhs: AB1, rhs: AB1) -> Bool { return true } } struct AB2: A, B, Hashable { func a() -> String { return "AB2.a" } func b() -> String { return "AB2.b" } var hashValue: Int { return 2 } static func ==(lhs: AB2, rhs: AB2) -> Bool { return true } } struct AnyABHashable: A, B, Hashable { let equalsClosure: (_ rhs: AnyABHashable) -> Bool let hashValueClosure: () -> Int let bClosure: () -> String let aClosure: () -> String static func ==(lhs: AnyABHashable, rhs: AnyABHashable) -> Bool { return lhs.equalsClosure(rhs) } var hashValue: Int { return hashValueClosure() } func b() -> String { return bClosure() } func a() -> String { return aClosure() } } // AB1 init extension AnyABHashable { init(_ ab1: AB1) { equalsClosure = { (r) in if let rhs = r as? AB1 { return ab1 == rhs } return false } hashValueClosure = { return ab1.hashValue } aClosure = { return ab1.a() } bClosure = { return ab1.b() } } } // AB2 init extension AnyABHashable { init(_ ab2: AB2) { equalsClosure = { (r) in if let rhs = r as? AB2 { return ab2 == rhs } return false } hashValueClosure = { return ab2.hashValue } aClosure = { return ab2.a() } bClosure = { return ab2.b() } } } let ab1Set = Set([AnyABHashable(AB1())]) let ab2Set = Set([AnyABHashable(AB2())]) let abSet = ab1Set.union(ab2Set) for ab in abSet { ab.a() ab.b() } On Tue, 11 Jul 2017 at 8:10 pm, Glen Huang via swift-users < swift-users@swift.org> wrote: > Hi, > > I want to store some heterogeneous items all conform to a protocol inside > a set, is it something possible to do in swift? > > I tried this example: > > ``` > protocol Named: Hashable { > var name: String { get } > } > > extension Named { > var hashValue: Int { > return name.hashValue > } > > static func ==(lhs: Self, rhs: Self) -> Bool { > return lhs.name == rhs.name > } > } > > struct Foo: Named { > var name = "foo" > } > > struct Bar: Named { > var name = "bar" > } > > var item = Set<Named>() > item.insert(Foo()) > item.insert(Bar()) > ``` > > But it failed at `Set<Named>()` where it complained "Using 'Named' as a > concrete type conforming to protocol 'Hashable' is not supported”. > > After watching the WWDC session "Protocol-Oriented Programming in Swift” > by Dave Abrahams, I try to use protocols whenever possible. But I can’t > seem to overcome this barrier. Set.Element must confirm to Hashable, which > inherits from Equatable, which has self requirement, which ultimately means > that Set.Element all must be of the same type. So it seems it’s impossible > to have heterogeneous items using protocol. Is that the case? > > My use case is this: > > I have an object that can contain two sets of other objects: > > ``` > class Parent { > var foos: Set<Foo> > var bars: Set<Bar> > } > ``` > > I want to define a computed property “all” that is the union of the two > sets. Foo and Bar conform to the same protocol. I wonder what return type I > should use for the union? Do I have to go back to OOP and define a super > class for Foo and Bar? > > Thanks. > _______________________________________________ > swift-users mailing list > swift-users@swift.org > https://lists.swift.org/mailman/listinfo/swift-users > -- -- Howard.
_______________________________________________ swift-users mailing list swift-users@swift.org https://lists.swift.org/mailman/listinfo/swift-users