SJ3040
SJ3040

Reputation: 156

Implementing generic protocols Error by compiler

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

Answers (1)

Gonzo
Gonzo

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

BaseProtocol declaration with Types highlighted

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>()

A declaration with types hightlighted

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

Related Questions