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?