2

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.

2

1 Answer 1

3

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.

Sign up to request clarification or add additional context in comments.

3 Comments

On doing 'class A<ChildPresenter> : ChildProtocol { var presenter: ChildPresenter? }'
Compiler is throwing error: 'ChildProtocol' requires the types 'ChildPresenter' and 'ChildPresenter' be equivalent class A<ChildPresenter>: ChildProtocol { note: requirement specified as 'Self.PresenterType' == 'ChildPresenter' [with Self = A<ChildPresenter>] class A<ChildPresenter>: ChildProtocol {
You have to remove the where clause on ChildProtocol's declaration

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.