Swift Protocol Constraints Relationship

25 views Asked by At

I'm trying to figure out if it's possible to create/compose a protocol relationship like this:

Considere a protocol HasAction, that needs an "enum: String" like so

protocol HasActions<ChoiceEnum> {
    associatedtype ChoiceEnum: RawRepresentable where ChoiceEnum.RawValue: StringProtocol
    func action(_ choice: ChoiceEnum)
}

Now the "concrete" Foo Action protocol would be defined as:

enum ActionsFooEnum: String { case foo, fooo, foooo }

protocol HasFooAction: HasActions<ActionsFooEnum> {}
// or?
protocol HasFooAction2: HasActions where ChoiceEnum == ActionsFooEnum {}
// or?
typealias HasFooAction3 = HasActions<ActionsFooEnum>

At this point, an object implementing HasFooAction is capable of knowing what enum can be found in action(...)

Now, let's define a generic User protocol like so-ish

protocol User<ChoiceEnum> {
    associatedtype ChoiceEnum: RawRepresentable where ChoiceEnum.RawValue: StringProtocol
    associatedtype HasConcreteActions: HasActions<ChoiceEnum>
}
// or ideally
protocol User {
    associatedtype HasConcreteActions: HasActions
    // but later on I'm blocked because I need to define it i.e. as HasActions<ActionsFooEnum>
}

The goal is to then use User and a "concrete" HasActions together.

protocol UserWithFooActions: User<ActionsFooEnum> where HasConcreteActions: HasFooAction {
    func hasBeenCalled()
    func hasBeenSeen()
}

But in the end when I try to use it on some class, it looks like it can't infer what HasConcreteActions is :/

class UserWithActions: UserWithActionFoo {
    var fooActions: (any HasConcreteActions)?

    func didCallMe() {
        fooActions?.action(.fooo)
    }
    
    func didTalkToMe() {
        fooActions?.action(.foo)
    }
}

I don't understand why the compiler still asks me for

    typealias ChoiceEnum = ActionsFooEnum
    typealias HasConcreteActions = HasActions<ActionsFooEnum>
    // the compiler then still asks me to define HasConcreteActions :o

Does anyone can indicate me if I'm doing something wrong, or if I try to do is not possible? Where is the bottleneck? Maybe the relationship can be defined differently?

0

There are 0 answers