Thanks for the detailed example.

It makes sense. But the code can grow pretty quickly with just a few methods 
and a few concrete types. Also most are repetitive. I’ll try to incorporate 
this pattern when the use case is simple. But for more complex ones I guess I 
have to stick with classes for now.

> On 12 Jul 2017, at 8:07 AM, Howard Lovatt <howard.lov...@gmail.com> wrote:
> 
> I would be tempted to use classes for this if you can use single inheritance. 
> If you need multiple inheritance then use an enum and hand code the dispatch, 
> a lot more work :(. 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
>     }
> }
> enum AB1Or2: A, B, Hashable {
>     case ab1(AB1)
>     case ab2(AB2)
>     func a() -> String {
>         switch self {
>         case .ab1(let ab1Arg): 
>             return ab1Arg.a()
>         case .ab2(let ab2Arg): 
>             return ab2Arg.a()
>         }
>     }
>     func b() -> String {
>         switch self {
>         case .ab1(let ab1Arg): 
>             return ab1Arg.b()
>         case .ab2(let ab2Arg): 
>             return ab2Arg.b()
>         }
>     }
>     var hashValue: Int {
>         switch self {
>         case .ab1(let ab1Arg): 
>             return ab1Arg.hashValue
>         case .ab2(let ab2Arg): 
>             return ab2Arg.hashValue
>         }
>     }
>     static func ==(lhs: AB1Or2, rhs: AB1Or2) -> Bool {
>         switch lhs {
>         case .ab1(let lhsAB1):
>             switch rhs {
>             case .ab1(let rhsAB1): 
>                 return lhsAB1 == rhsAB1
>             default:
>                 return false
>             }
>         case .ab2(let lhsAB2):
>             switch rhs {
>             case .ab2(let rhsAB2): 
>                 return lhsAB2 == rhsAB2
>             default:
>                 return false
>             }
>         }
>     }
> }
> let ab1s = Set([AB1Or2.ab1(AB1())])
> let ab2s = Set([AB1Or2.ab2(AB2())])
> let abs = ab1s.union(ab2s)
> 
> 
> On Tue, 11 Jul 2017 at 10:46 pm, Glen Huang <hey...@gmail.com 
> <mailto:hey...@gmail.com>> wrote:
> Thanks for bringing AnyHashable to my attention.
> 
> It works, but the types are now erased. I want to have a union of the two 
> sets because I want to loop over it to treat each contained item as Named, so 
> I can process them as though they are of the same type. Is this type of use 
> case really should be addressed using super class?
> 
>> On 11 Jul 2017, at 7:38 PM, Howard Lovatt <howard.lov...@gmail.com 
>> <mailto:howard.lov...@gmail.com>> wrote:
>> 
>> You can have a set of AnyHashable:
>> 
>>> var item = Set<AnyHashable>()
>>> item.insert(AnyHashable(Foo()))
>>> item.insert(AnyHashable(Bar()))
>> 
>> Depends what you will do with the set if this is viable or not. You can also 
>> use classes and ObjectID.
>> 
>> You might want this though:
>> 
>>> var item = [AnyHashable: Any]
>> extension Dictionary where Key == AnyHashable, Value: Hashable {
>>     func insert(_ value: Value) {
>>         self[AnyHashable(value)] == value
>>     }
>> }
>>> item.insert(Foo())
>>> item.insert(Bar())
>> 
>> So you get at the stored value.
>> 
>> -- Howard.
>> 
>> On 11 Jul 2017, at 8:09 pm, Glen Huang via swift-users 
>> <swift-users@swift.org <mailto: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 <http://lhs.name/> == rhs.name <http://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 <mailto:swift-users@swift.org>
>>> https://lists.swift.org/mailman/listinfo/swift-users 
>>> <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

Reply via email to