Как внедрить в общий протокол, который имеет функцию, использующую тип ассоциированного типа? - PullRequest
0 голосов
/ 30 мая 2019

Я создаю некоторый класс подтверждений для универсального протокола, этот универсальный протокол имеет метод, который принимает параметр типа associatedtype, я использую Xcode для создания заглушки для меня:


import UIKit

struct SomeObject: Codable {
    var id: String?
    var name: String?
}

protocol INetworkManager {
    associatedtype ResponseObject
    func get(url: String, ofType: ResponseObject.Type, completion: (ResponseObject?, Error?) -> Void)
}

class NetworkManager: INetworkManager {
    typealias ResponseObject = Codable

    func get(url: String, ofType: ResponseObject.Protocol, completion: (ResponseObject?, Error?) -> Void) {
        completion(SomeObject(id: "1", name: "hello"), nil)
    }
}

Вместо ResponseObject.Type он генерирует для меня ResponseObject.Protocol, на самом деле я не знаю, что это за ResponseObject.Protocol, и я не могу передать SomeObject.self в качестве параметра, подобного этому:

let networkManager = NetworkManager()
networkManager.get(url: "http://whatever.com", ofType: SomeObject.self) { (responseObject, error) in
    print("got response object named: \(responseObject.name)")
}

компилятор выдал мне эту ошибку:

error: Cannot convert value of type 'SomeObject.Type' to expected argument type 'NetworkManager.ResponseObject.Protocol' (aka '(Decodable & Encodable).Protocol')

Я думаю, что-то не так с моей реализацией, кто-нибудь может дать мне какие-нибудь идеи?

Спасибо!

1 Ответ

0 голосов
/ 31 мая 2019

Это не то, как работают связанные типы.get должно быть общим для своего типа ответа, но сам сетевой менеджер не является общим для какого-то определенного типа ответа.Я полагаю, что вы имели в виду следующее:

protocol NetworkManager {
    func get<ResponseObject>(url: String, 
                             ofType: ResponseObject.Type, 
                             completion: (Result<ResponseObject, Error>) -> Void) 
    where ResponseObject: Decodable
}

class TrivialNetworkManager: NetworkManager {
    func get<ResponseObject>(url: String, 
                             ofType: ResponseObject.Type, 
                             completion: (Result<ResponseObject, Error>) -> Void) 
    where ResponseObject: Decodable {
        completion(.success(SomeObject(id: "1", name: "hello"))
    }
}

Для более проработанной версии этой конкретной проблемы вы можете прочитать мою серию протоколов , но важная концепция здесь заключается в том, чтоNetworkManager не отличается от своего ResponseType, поэтому нет причин делать его ResponseType ассоциированным типом.

То, что вы написали, пытается сказать: «Некоторые сетевые менеджеры будут иметь Codable ResponseType, а другие сетевые менеджеры будут иметькакой-то другой тип ResponseType. "Не «какой-то другой конкретный тип ответа (например, Пользователь)», а «некоторый другой протокол, которому должны соответствовать его типы ответа».Хотя возможно создать что-то подобное, это намного сложнее, и вам нужно объяснить ваш конкретный вариант использования, чтобы спроектировать его.В частности, вам нужно показать несколько конкретных реализаций вашего протокола, чтобы увидеть, какой тип общего кода вы пытаетесь извлечь.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...