swift - Swift 5 中的 THE.self 是什么?

我目前正在浏览 Landmarks 应用程序教程,我在将 JSON 加载到结构中的部分。他们给出了以下代码。

引用:https://developer.apple.com/tutorials/swiftui/building-lists-and-navigation

import Foundation


func load<T: Decodable>(_ filename: String) -> T {

    let data: Data


    guard let file = Bundle.main.url(forResource: filename, withExtension: nil)

    else {

        fatalError("Couldn't find \(filename) in main bundle.")

    }


    do {

        data = try Data(contentsOf: file)

    } catch {

        fatalError("Couldn't load \(filename) from main bundle:\n\(error)")

    }


    do {

        let decoder = JSONDecoder()

        return try decoder.decode(T.self, from: data)

    } catch {

        fatalError("Couldn't parse \(filename) as \(T.self):\n\(error)")

    }

}

我特别不明白 T.self引用也不 <T: Decodable>在函数的开头。有人能分解这个功能吗?谢谢。

最佳答案

我看到这个问题在评论中得到了回答,但我觉得对于那些试图理解泛型的 Swift 新手来说,这个问题值得一个实际的回答。

为了回答这个问题,让我们看看T是什么,它定义在函数的签名中

func load<T: Decodable>(_ filename: String) -> T

这表示通用函数 load(_:String) -> T 返回一些符合 Decodable 的类型 T,所以 T 是引用返回值类型的通用方式,其中该类型将根据调用站点的上下文确定,具体而言,由接收返回值的任何类型决定。

被询问的行是

return try decoder.decode(T.self, from: data)

这里 T.self 是一种引用类型 T 本身的方式。如果您查看 decode 的函数签名,您会发现它看起来像这样:

func decode<T: Decodable>(_ type: T.Type, from data: Data) throws -> T

请注意,参数类型 T.Type type。这意味着参数 type 将保存类型 T 而不是类型 T 的值。这是 Swift 区分指定变量是类型的值还是它的值是类型本身的方法。一开始这可能有点令人困惑,但一旦您了解了泛型,它就会变得有意义。

因为 Swift 是一种强类型语言,类型是在编译时定义的,decode 需要知道它试图解码的对象的类型。在 JavaScript 或 Python 等无类型语言中,这不是必需的。在那些语言中,对象基本上是字典,因此它总是可以解码字典(或数组,或一小组基本类型之一)。在 Swift 中,structclass 只是字典的语法糖。它们更像是 C 风格的 struct - 一组二进制数据,具有由类型决定的特定内存布局。为了正确解码,decode 必须知道它在解码什么,而且最常见的是,如何通过它的 init(from: Decoder) throws 方法告诉那个东西解码自己(可能已由编译器合成)。它会调用 NSImage.init(from: Decoder) 还是 String.init(from: Decoder) 等...?

如果您熟悉在 OOP 中实现运行时多态性的方式,提供类型,甚至是一般性的,提供了一种获取类型的协议(protocol)见证表的方法 - 这是协议(protocol)等同于“vtable”该类用于虚拟方法的运行时动态分派(dispatch)。所以它让它做一些类似于在 OOP 中调用虚拟方法的事情,除了它通常可以在编译时计算出来,并且它可以同时适用于值类型和引用类型。了解他的工作原理还可以深入了解不同但相关的问题,例如为什么直接在协议(protocol)中声明的所需方法与仅在协议(protocol)扩展中声明的方法(基本上在协议(protocol)中直接声明的方法在协议(protocol)中)得到不同的多态行为witness 表,因此它们可以被动态调度,而仅在扩展中的那些不在 witness 表中,因此任何特定于类型的实现都将丢失,而只能调用协议(protocol)扩展中的实现)。

以下函数使用它来打印其参数的类型(有更好的方法,但这说明了 T.TypeT.self):

func foo<T>(_ value: T)
{
    let typeOfValue: T.Type = T.self
    print("The value, \(value), is of type, \(typeOfValue).")
}

https://stackoverflow.com/questions/66631340/

相关文章:

python - Pandas 根据条件转置

python - Where 函数忽略 Nan

r - 将唯一数字添加到字符串

kubernetes - 将单独的环境变量传递给 statefulset pod

vue.js - Primevue Grid 和 Flex 布局无法正确呈现

regex - 如何从日志文件中 grep 错误但过滤掉错误警报?

javascript - 我想从数组中返回一个 JSON 对象

delphi - 我们可以在 Sydney 的手机中安全地使用 ansiString 吗?

c++ - 有没有办法进行编译时检查,一个类的所有成员都在 operator== 中进行比较

webpack - 为什么 Tailwind 中的清除选项不适用于 Webpack