【问题标题】:Difference between T and Self in generic methods泛型方法中 T 和 Self 的区别
【发布时间】: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


【解决方案1】:

您使用Self 的第二个实现符合您的要求。您想在协议中创建一个初始化程序,您可以在要初始化的类型上调用它。协议函数中的Self 指的是你调用特定方法的类型。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-16
    • 1970-01-01
    • 2023-03-17
    • 2015-05-30
    • 1970-01-01
    相关资源
    最近更新 更多