4bottiglie 4bottiglie - 4 months ago 19
Swift Question

Array with associatedtype protocol

I'am coming from java and I have little difficulties to learn the patterns.

I have the first protocol

protocol Interval
{

}


And the second:

protocol Event
{
associatedtype IntervalType: Interval

var interval: IntervalType

func doSomething(param: IntervalType )
}


How can i make an array with the type Event?

I took a look at the type-erase and the solution that it gives it to create a struct like this one:

public struct AnyEvent<intervalType: Interval>: Event {...}


But it only gives me the possibility to create an array with any event type and only one type of Interval, I want to make an array with any kind of Events that could contain any kind of Intervals, something like:
[AnyEvent]
or
[AnyEvent<Interval>]


I also want to ask if there is a possibility to make Event extend Equatable and define it in the type-erase.

Answer

As you know in Swift you cannot declare an array of a protocols with an associated type (please read this for more details)

However you can declare a new protocol like this

protocol AnyEvent {
    var interval: Interval { get }
    func doSomething(param: Interval )
}

Your 3 protocols should now looks like this

protocol Interval {

}

protocol AnyEvent {
    var interval: Interval { get }
    func doSomething(param: Interval )
}

protocol Event: AnyEvent {
    associatedtype IntervalType: Interval
    var interval: IntervalType { get }
    func doSomething(param: IntervalType )
}

Usage

To use these protocols we need some structs (or classes) that conform to them

struct TimeInterval: Interval { }
struct TapEvent: AnyEvent {
    var interval: Interval = TimeInterval()
    func doSomething(param: Interval) {
        print("It's a tap")
    }
}
struct GestureEvent: AnyEvent {
    var interval: Interval = TimeInterval()
    func doSomething(param: Interval) {
        print("It's a gesture")
    }
}

Now we can

var events = [AnyEvent]()
events.append(TapEvent())
events.append(GestureEvent())
for event in events {
    event.doSomething(TimeInterval())
}

It's a tap

It's a gesture

I also want to ask if there is a possibility to make Event extend Equatable and define it in the type-erase

Yes you just need to add the declaration

protocol Event: AnyEvent, Equatable {
    associatedtype IntervalType: Interval
    var interval: IntervalType { get }
    func doSomething(param: IntervalType )
}

Now you are forcing every struct o class conform to Event to be Equatable.

Comments