首页 > 解决方案 > 符合更指定的协议扩展版本

问题描述

假设有一个空协议来限制类型:

public protocol DataType { }

protocol Parser {
    func parseData<T: DataType>(_ data: Data, to: T.Type) throws -> T
}

所以我们需要一个专门用于解析 JSON 对象的解析器:

typealias DecodableDataType = Decodable & DataType

protocol JSONParser: Parser {
    var jsonDecoder: JSONDecoder { get }
    func parseData<T: DecodableDataType>(_ data: Data, to: T.Type) throws -> T
}

所以它也符合parser需求,正如jsonDecoder已经定义的那样,一个简单的extension会很棒:

extension JSONParser {
    func parseData<T: DecodableDataType>(_ data: Data, to: T.Type) throws -> T { try jsonDecoder.decode(T.self, from: data) }
}

因此,如果我们为此实现一个管理器类:

class JSONParsingManager: JSONParser {
    public var jsonDecoder: JSONDecoder

    init(jsonDecoder: JSONDecoder) {
        self.jsonDecoder = jsonDecoder
    }
}

期望一切都会自动运行,但它会抛出:

类型“JSONParsingManager”不符合协议“解析器”

我错过了什么?我需要为其他序列化程序(如 Protobuf 解析器等)定义管理器,所以我不能一开始就遵守Decodable


更明确:

另一个应该以相同方式工作的协议:

protocol ProtobufParser: Parser {
    func parseData<T: Message>(_ data: Data, to: T.Type) throws -> T
}

extension ProtobufParser {
    func parseData<T: Message>(_ data: Data, to: T.Type) throws -> T { try T.init(serializedData: data) }
}

更新

我不能定义独立的协议,因为有一个函数需要获取任何类型的Parser来解析任何可解析的对象。

PS这个问题之前可能已经用不同的标题和场景提出过。如果您知道应该如何提出这个问题,请随时提及答案。

标签: swiftprotocols

解决方案


错误信息是准确的。协议的要求是

func parseData<T: DataType>(_ data: Data, to: T.Type) throws -> T

但是你有一个实现的扩展

func parseData<T: Decodable & DataType>(_ data: Data, to: T.Type) throws -> T

即你的解析器只能解析那些东西,Decodable但是你的协议说它必须能够解析任何符合DataType.


您也许可以使用 where 子句来指定更具体的要求

extension JSONParser {
  func parseData<T: DataType>(_ data: Data, to: T.Type) throws -> T where T: Decodable {
    try jsonDecoder.decode(T.self, from: data)
  }

  func parseData<T: DataType>(_ data: Data, to: T.Type) throws -> T {
    throw CannotDecodeError
  }
}

推荐阅读