0
votes

I want to write two protocols, one generic and one more specific to handle some network requests.

All works fine for the more generic DORequest protocol, but I can’t get DOPagedRequest working. The problem is caused by associatedtype Response, that I want to make more specific in DOPagedRequest.

Here are my protocols:

public protocol DORequest {
    associatedtype Response: DOResponse
    var method: String { get }
    var path: String { get }
}

public protocol DOResponse: Codable { }

public protocol DOPagedRequest: DORequest where Response: DOPagedResponse {
    var page: Int? { get }
    var perPage: Int? { get }
}

public protocol DOPagedResponse: Codable {
    var links: ResponseLinks { get }
}

public struct ResponseLinks: Codable {

    public struct Pages: Codable {
        var next: String?
    }

    public var pages: Pages?
}

And their concrete implementation example:

// Implementation of DORequest with no errors
public struct Get: DORequest {

    public struct Response: DOResponse {
        public let account: String
    }

    public let method = "GET"
    public let path = "account"

    public init() { }
}

// Implementation of DOPagedRequest with errors:
//  Type 'List' does not conform to protocol 'DORequest'
//  Type 'List' does not conform to protocol 'DOPagedRequest'
public struct List: DOPagedRequest {

    public var tag: String?
    public var page: Int?
    public var perPage: Int?

    public struct Response: DOPagedResponse {
        public var links: ResponseLinks

        public let droplets: [String]
    }

    public let method = "GET"
    public let path = "droplets"

    public init(tag: String? = nil, page: Int = 0, perPage: Int = 200) {
        self.tag = tag
        self.page = page
        self.perPage = perPage
    }
}

Probably I'm missing something about Swift's associatedtype.

2
What is DO? It looks like an Objective-C prefix. – Jessy
DO stands for Digital Ocean, I am writing an API wrapper πŸ˜… – alessionossa
But in Swift, you can use a module. You don't need a prefix. – Jessy

2 Answers

1
votes

You forgot to inherit from DOResponse.

public protocol DOPagedResponse: DOResponse {
1
votes

There are a couple of things in your code that don't make much sense to me.

The main point that i do not understand is the nature of Response:

Response in DORequest is: associatedtype Response: DOResponse

Response in DOPagedRequest is where Response: DOPagedResponse.

So when you declare public struct List: DOPagedRequest the compiler won't be able to figure out to which Type does Response conform to.

is it Response of type DOResponse or of type DOPagedResponse?

I would suggest you do something to unite the 2 protocols, namely: DOResponse and DOPagedResponse under the same umbrella, something like this:

public protocol GeneralResponse {}

public protocol DOResponse: Codable, GeneralResponse { }
public protocol DOPagedResponse: Codable, GeneralResponse {
   var links: ResponseLinks { get }
}

public protocol DORequest {
  associatedtype Response: GeneralResponse
  var method: String { get }
   var path: String { get }
}

public protocol DOPagedRequest {
   var page: Int? { get }
   var perPage: Int? { get }
}