0
protocol ApiRequest {
    associatedtype DataType

    func execute() -> DataType
}

class SomeApiRequestMock: ApiRequest {
    typealias DataType = String

    func execute() -> String {
        return "1"
    }
}



class Simple<D: ApiRequest>{
    func creatorMock(_ request: D) -> D.DataType {
        request.execute()
    }
}
extension Simple where D: SomeApiRequestMock {
    var request: SomeApiRequestMock {
        return SomeApiRequestMock()
    }

    var create: D.DataType {
        creatorMock(request)
    }
}

I have this ApiRequest protocol and create some concrete class conformed this ApiRequest protocol. then I try to use it in some Generic constraint class Simple. The compiler was happy initially, until I try to call the creatorMock: func in extensions. and I'll get enter image description here I could solve it by adding the same constraint again in method like func creatorMock<D: ApiRequest>(_ request: D) -> D.DataType

but I don't understand why is that? anyone could help to explain what's going on here?

Wenzhong
  • 13
  • 3
  • Regarding `API`: "[Acronyms and initialisms that commonly appear as all upper case in American English should be uniformly up- or down-cased according to case conventions](https://swift.org/documentation/api-design-guidelines/)" –  Mar 10 '20 at 00:22
  • I think you can rip out of a lot of the complexity here (associated types, return values, function implementations) while still faithfully reproducing the problem. What do you think? https://gist.github.com/amomchilov/bd43e72ac2c7e37e54250ea7d8a4975b – Alexander Mar 10 '20 at 02:10
  • I think this happens because `var request: SomeApiRequestMock` is returning a "protocol existential". Protocol existential, strangely, don't conform to the protocols they themselves stand in for. Check out https://stackoverflow.com/a/43408193/3141234 – Alexander Mar 10 '20 at 02:19

1 Answers1

0

Two solutions, depending on your needs:


Using == instead of : is simpler.

extension Simple where D == SomeAPIRequestMock {

Otherwise, you need to append an initializer to your protocol, or, probably more simply, your mock:

class SomeAPIRequestMock: APIRequest {
  required init() { }

You'll also need to return D, not an instance of its superclass.

extension Simple where D: SomeAPIRequestMock {
  var request: D { .init() }
  var create: D.DataType { creatorMock(request) }
}
  • 1
    Thank you so much Jessy ! Both solution works fine. I'm just confused why the second solution ` extension Simple where D: SomeAPIRequestMock { var request: D { .init() } var create: D.DataType { creatorMock(request) } } ` works but not ` var request: SomeApiRequestMock { return SomeApiRequestMock() } var create: D.DataType { creatorMock(request) } ` both look legit to me. Why mine is not working. trying to find out the reasons behind that. I much appreciate for your solution again. works like a charm – Wenzhong Mar 10 '20 at 00:46