swift - 符合更指定的协议扩展版本
问题描述
假设有一个空协议来限制类型:
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这个问题之前可能已经用不同的标题和场景提出过。如果您知道应该如何提出这个问题,请随时提及答案。
解决方案
错误信息是准确的。协议的要求是
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
}
}
推荐阅读
- connection - Lisp IDE Portacle tells me "lisp connection closed unexpectedly connection broken by remote peer"
- angular - how can i make file downloadable in angular?
- spring-boot - Spring: map entity to a scheme
- reactjs - Disable swipe while using in stack navigator 4.0
- node.js - Node.js convert bitmap string data to base64
- javascript - How to place ejs in loops
- flutter - Import And Export Sqflite File using firebase and flutter
- c - palindrome c program is not working for some reason
- java - Install JDK on Apache Airflow Helm Charts
- html - CSS Hover - 悬停时淡入,悬停后立即消失