泛型方法中 T 和 Self 之间的区别



我正在编写一个名为JSONDataInitializable的协议,它将允许使用JSONDecoder从包含 JSON 的Data初始化值。

由于无法在初始值设定项中显式使用泛型,因此我在协议扩展中声明了一个通用的、与类型无关的帮助程序方法,初始值设定项稍后会调用该方法。

但是,我想出了不是一种,而是两种方法来编写这样的方法。

(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)

使用Self的第二个实现是符合您要求的实现。您希望在协议中创建初始值设定项,您可以对要初始化的类型调用该初始值设定项。 协议函数中的Self是指调用特定方法的类型。

另一方面,泛型实现将允许您初始化符合协议的任何类型,但在init(from:)方法中,您将返回值分配给self,因此泛型类型参数T将被推断为Self。这使得没有必要使该方法泛型,因为在特定类型上,T将始终Self

最新更新