【发布时间】:2019-03-29 09:03:28
【问题描述】:
我正在编写一个名为 JSONDataInitializable 的协议,它可以使用 JSONDecoder 从包含 JSON 的 Data 初始化值。
由于it’s not possible 在初始化程序中显式使用泛型,我在协议扩展中声明了一个通用的、类型不可知的辅助方法,初始化程序稍后会调用该方法。
但是,我想出了两种方法来编写这样的方法。
(1):
private static func initialize<T: JSONDataInitializable>(from jsonData: Data) throws -> T {
return try JSONDecoder().decode(T.self, from: jsonData)
}
(2):
private static func initialize(from jsonData: Data) throws -> Self {
return try JSONDecoder().decode(Self.self, from: jsonData)
}
您能解释一下这些方法之间的区别吗?它们似乎都产生了相同的结果。
唯一可见的区别是第一个变体中的协议一致性部分。但是,这些方法是在协议扩展中声明的,因此仅适用于符合协议的类型。
UPD
这是完整的协议声明:
protocol JSONDataInitializable: Decodable {
init?(from jsonData: Data)
}
extension JSONDataInitializable {
init?(from jsonData: Data) {
do {
self = try Self.initialize(from: jsonData)
} catch {
print(error)
return nil
}
}
// (1)
private static func initialize<T: JSONDataInitializable>(from jsonData: Data) throws -> T {
return try JSONDecoder().decode(T.self, from: jsonData)
}
// ⬆⬆⬆
// OR
// ⬇⬇⬇
// (2)
private static func initialize(from jsonData: Data) throws -> Self {
return try JSONDecoder().decode(Self.self, from: jsonData)
}
}
假设我们有一个名为User 的结构,即Decodable。我们需要从 JSON 中初始化 User 的值(存储为 Data)。使用该协议,初始化工作如下:
// Protocol conformance declaration
extension User: JSONDataInitializable { }
// JSON stored as Data
let networkData = ...
// Initialization
let john = User(from: networkData)
【问题讨论】:
-
第一种方法不需要自定义协议,只需将
T限制为Decodable。此外,如果您包含 minimal reproducible example 会有所帮助,尤其是显示这些方法的声明位置(在什么范围内)。 -
@DávidPásztor 感谢您的评论。我添加了完整的协议声明。
标签: swift generics protocols swift-protocols