Значение аргумента по умолчанию типа 'JSONEncoder' не может быть преобразовано в тип 'Encoder' (TopLevelEncoder) - PullRequest
0 голосов
/ 22 октября 2019

Я пытался создать универсальный метод, который принимает TopLevelEncoder и TopLevelDecoder, чтобы сделать его инъекционным (например, JSONEncoder в рабочем коде и CustomEncoder для тестирования). Поскольку оба протокола имеют связанные типы, я ограничиваю их тип, а не просто encoder: TopLevelEncoder = JSONEncoder(). Я придумал этот метод:

func test<Encoder, Decoder>(
    encoder: Encoder = JSONEncoder(),
    decoder: Decoder = JSONDecoder()
) where Encoder: TopLevelEncoder, Decoder: TopLevelDecoder {
    //encode and decode
}

Компилятор выдает мне следующее сообщение об ошибке: Default argument value of type 'JSONEncoder' cannot be converted to type 'Encoder'. Я не понимаю, как его нельзя преобразовать в тип Encoder, поскольку JSONEncoder наследуется от TopLevelEncoder.

Возможно, я неправильно понимаю, как работают дженерики и associatedType, но я не могу обернуть своюОбойдите это сообщение об ошибке либо. Может ли кто-нибудь помочь мне?

Я видел другие подходы к этой проблеме, такие как создание нового протокола, такого как AnyEncoder, и расширение JSONEncoder с ним. Но, на мой взгляд, было бы проще использовать существующий протокол. Также мой метод требует TopLevelDecoder, так как я использую URLSessions s .dataTaskPublisher (.decode(...)).

1 Ответ

0 голосов
/ 06 ноября 2019

Я не знаю, насколько безопасно применять принудительное приведение в этой ситуации, но, похоже, это компилируется и работает:

struct User: Codable {
    var name: String
}

func decodeEncode<Encoder, Decoder>(
  encoder: Encoder = JSONEncoder() as! Encoder, 
  decoder: Decoder = JSONDecoder() as! Decoder) 
  where Encoder: TopLevelEncoder, Decoder: TopLevelDecoder, 
        Encoder.Output == Data, Decoder.Input == Data
{
    let bruceData = try! encoder.encode(User(name: "Bruce Lee"))
    let bruce = try! decoder.decode(User.self, from: bruceData)

    print("bruce: \(bruce)")
}

decodeEncode(encoder: JSONEncoder(), decoder: JSONDecoder())

Возможно ограничение Encoder.Output == Decoder.Input, но я явно указал Data потому что JSONEncoder и JSONDecoder оба работают с Data.

...