I am trying to create a generic structure in my project and I am facing an issue where I get the error "Type 'any B' cannot conform to 'A'"
, where protocol B is derived from protocol A.
I don't understand why such a structure is problematic and I would really appreciate any insight or alternative solution for this issue I am having.
Issue:
I have a general base protocol-class pair like the following.
protocol A { }
class AClass<T: A> { }
- To give an example of my use case, protocol
A
can bePresenterLogic
whereAClass
isBaseInteractor
.
I have a second protocol-class pair which I want to specialize according to its use case.
protocol B: A { }
class BClass: AClass<B> { } // Here, I get "Type 'any B' cannot conform to 'A'"
- For example, protocol
B
beingMyPresenterLogic
and classBClass
beingMyInteractor
.
Specific Use-Case:
To give a more specific use case, I am trying to build a VIP
structure such as the following.
// Base VIP (Ex: Interactor)
protocol PresenterLogic {
}
class Interactor<PL: PresenterLogic>, BusinessLogic {
var presenter: PL?
}
// VIP for Specific Screen (Ex: Interactor)
protocol MyPresenterLogic: PresenterLogic {
}
class MyInteractor: Interactor<MyPresenterLogic> {
// I don't want to declare a second `myPresenter: MyPresenterLogic` here
}
I don't want to declare another presenter instance in MyInteractor
, (such as myPresenter: MyPresenterLogic
. I want to be able to use the same presenter instance to be inferred to have the sub-protocol type.
That is why I want to use generic classes, but I am stuck. I am searching if this is supported. Any insight is appreciated. Thank you.
The error message is correct. Your code:
protocol B: A { }
class BClass: AClass<B> { }
by definition means:
protocol B: A { }
class BClass: AClass<any B> { }
That says that BClass
is a subclass of a specialization of AClass<T>
where T
is the existential type any B
. However, your definition of A is:
protocol A { }
class AClass<T: A> { }
This by definition means that T
is a concrete type that conforms to A
. any B
is an existential type, not.a concrete type, so it's can't work for classA
.
To get around this, you can do this:
protocol B: A { }
class BClass<U: B>: AClass<U> { }
In other words, make BClass
also generic, taking a concrete type U
that conforms to B and hence conforms to A.
However, if you need BClass
to really be specialized on any B
, you'll have to do something to AClass
to let it take an existential type as a parameter.