Ankit Sachan
Ankit Sachan

Reputation: 7850

How to declare a generic protocol property requirement in a protocol

Struggling for a while with, it will be really helpful if you can shed some light on this:

I have an APIWorkerProtocol which has a property requirement, the required property is a protocol i.e DataParserProtocol

protocol APIWorkerProtocol {
    var apiRequestProvider : APIRequestGeneratorProtocol {get}
    var dataParser : DataParserProtocol{get}
    func callAPI(completionHandler: @escaping (APICallResult<Self.ResultType>) -> Void)
}

protocol DataParserProtocol {
    associatedtype ExpectedRawDataType
    associatedtype ResultType
    func parseFetchedData(fetchedData : ExpectedRawDataType) -> APICallResult<ResultType>
}

How can I achieve this?

In this current implementation, this causes an error Protocol 'DataParserProtocol' can only be used as a generic constraint because it has Self or associated type requirements.

Thanks in advance

Ankit

Upvotes: 2

Views: 2725

Answers (1)

dfrib
dfrib

Reputation: 73206

If a protocol make use of Self or associated type requirements (a homogenous protocol), we may note use the protocol as a concrete type.

So instead of using the DataParserProtocol as the concrete type of the dataParser property (blueprinted in the APIWorkerProtocol), you could add an associatedtype typeholder, say DataParser, to the APIWorkerProtocol, which is constrained to types that conform to the DataParserProtocol.

Also, I'm not sure what the intent with using Self.ResultType as specialization in the completion handler of callAPI(...) is (since Self would refer to the type implementing the APIWorkerProtocol; a protocol which blueprints no associatedtype ResultType): did you mean to use the ResultType of the DataParserProtocol type?

E.g.

protocol APIWorkerProtocol {
    associatedtype DataParser: DataParserProtocol
    var dataParser : DataParser { get }
    func callAPI(completionHandler: @escaping (APICallResult<DataParser.ResultType>) -> Void)
}

protocol DataParserProtocol {
    associatedtype ExpectedRawDataType
    associatedtype ResultType
    func parseFetchedData(fetchedData: ExpectedRawDataType) -> APICallResult<ResultType>
}

Upvotes: 6

Related Questions