Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pure swift set with protocol objects

Tags:

Is there a way to make the following actually work?

V1 - "test protocol does not conform to Hashable"

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

V2 - "Protocol 'testProtocol' can only be used as a generic constraint because it has Self or associated type requirements

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

I'm assuming that the answer is no - because protocols (even with the @objc tag) do not have enough information?? but maybe there is some sort of line or thing i'm missing here.

like image 562
Jeef Avatar asked Mar 26 '15 12:03

Jeef


People also ask

Can we create object of protocol Swift?

You can not create an instance of protocol. But however you can refer an object in your code using Protocol as the sole type.

Can a protocol conform to hashable?

You can use any type that conforms to the Hashable protocol in a set or as a dictionary key. Many types in the standard library conform to Hashable : Strings, integers, floating-point and Boolean values, and even sets are hashable by default.

CAN protocols have properties in Swift?

A protocol can have properties as well as methods that a class, enum or struct conforming to this protocol can implement. A protocol declaration only specifies the required property name and type.

CAN protocol inherit in Swift?

One protocol can inherit from another in a process known as protocol inheritance. Unlike with classes, you can inherit from multiple protocols at the same time before you add your own customizations on top. Now we can make new types conform to that single protocol rather than each of the three individual ones.


2 Answers

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!

like image 167
Sam Deane Avatar answered Oct 02 '22 15:10

Sam Deane


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() { } } 
like image 20
Martin R Avatar answered Oct 02 '22 14:10

Martin R