Reputation: 156
I am trying to use generic protocols in my Application. Code which I am trying to use is something like this.
protocol BaseProtocol {
associatedtype PresenterType
var presenter: PresenterType? { get set }
}
protocol PresenterProtocol {
associatedtype View
var view: View? { get set }
}
protocol ChildPresenter: PresenterProtocol where View == ChildProtocol {
}
protocol ChildProtocol: BaseProtocol where PresenterType == ChildPresenter {
}
class A: ChildProtocol {
var presenter: ChildPresenter?
}
Compiler is throwing error while conforming to ChildProtocol
error: protocol 'ChildPresenter' can only be used as a generic constraint because it has Self or associated type requirements var presenter: ChildPresenter?
I am not getting why compiler is throwing this error when I have already cleared my associateType.
Upvotes: 2
Views: 65
Reputation: 1553
As the error says, ChildPresenter
can olny be used as a generic, so you have to place it on the declaration of the class, eg. class A<T: ChildPresenter> : ChildProtocol
protocol BaseProtocol {
associatedtype PresenterType
var presenter: PresenterType? { get set }
}
protocol PresenterProtocol {
associatedtype View
var view: View? { get set }
}
protocol ChildPresenter: PresenterProtocol where View == ChildProtocol {
}
protocol ChildProtocol: BaseProtocol {
}
class A<T: ChildPresenter> : ChildProtocol {
var presenter: T?
func foo(bar: T) {
}
}
You also can use ChildPresenter
instead of T
, like this
class A<ChildPresenter> : ChildProtocol {
var presenter: ChildPresenter?
}
At first it seems that this limits a little bit your class A
, because you have to specify the type of ChilPresenter before initialization, and it can't be modified later, but this is necessary because ChildPresenter
has a associated type.
You can see that without the generic you could get into trouble, imagine that BaseProtocol
had one more property
protocol BaseProtocol {
associatedtype PresenterType
var presenter: PresenterType? { get set }
var presented: PresenterType? { get set }
}
Both presenter
and presented
have to be the same type, because you said it here
And class A
would have one more property too:
class A<ChildPresenter> : ChildProtocol {
var presenter: ChildPresenter?
var presented: ChildPresenter?
}
This way, you guarantee that both presenter
and presented
will have always the same type, because you choose that type when you created an object of A
, eg. let a = A<Foo>()
Without the generic, it would look something like this
class A: ChildProtocol {
var presenter: ChildPresenter?
var presented: ChildPresenter?
}
And in this way, presenter
could be of type Foo
and presented
could be of type Bar
. So you end up with a paradox. Thats why you need to set the generic type in A
's declaration.
Upvotes: 3