Swift 5 中的 THE.self 是啥?
Posted
技术标签:
【中文标题】Swift 5 中的 THE.self 是啥?【英文标题】:What is T.self in Swift5?Swift 5 中的 THE.self 是什么? 【发布时间】:2021-03-15 01:40:28 【问题描述】:我目前正在学习 Landmarks 应用教程,我正在学习将 JSON 加载到 Struct 中的部分。他们给出了以下代码。
参考: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>
。有人可以分解功能吗?谢谢。
【问题讨论】:
你知道String.self
或Int.self
或SomeType.self
是什么意思吗?
我知道self
指的是有问题的对象本身,但我并不完全清楚
没有。 String.self
表示字符串本身,类型。
嗯,有道理
docs.swift.org/swift-book/LanguageGuide/Generics.html
【参考方案1】:
我看到这个问题在 cmets 中得到了回答,但我觉得对于刚接触 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
请注意,参数类型type
显示为T.Type
。这意味着参数type
将保存T
类型而不是T
类型的值。这是 Swift 区分指定变量是类型的值与指定变量的值是类型本身的方式。起初这可能有点令人困惑,但一旦您了解泛型,它就会变得有意义。
因为 Swift 是一种强类型语言,类型是在编译时定义的,decode
需要知道它试图解码的东西的类型。在 javascript 或 Python 等无类型语言中,这不是必需的。在这些语言中,对象基本上是字典,因此它总是可以解码字典(或数组,或一小组基本类型中的一个)。在 Swift 中,struct
和 class
不只是字典的语法糖。它们更像 C 风格的 struct
- 一组二进制数据,具有由类型确定的特定内存布局。为了正确解码,decode
必须知道它正在解码什么,并且最常见的是,如何通过它的 init(from: Decoder) throws
方法(可能已经由编译器合成)告诉那个东西自己解码。它是调用NSImage.init(from: Decoder)
,还是String.init(from: Decoder)
,等等...?
如果您熟悉在 OOP 中实现运行时多态性的方式,则提供类型(即使是一般性的)提供了一种获取类型的协议见证表的方法 - 这在协议中相当于“vtable”该类用于虚拟方法的运行时动态调度。所以它让它做一些类似于在 OOP 中调用虚方法的事情,除了它通常可以在编译时计算出来,它可以同时适用于值类型和引用类型。了解他的作品如何还可以深入了解不同但相关的问题,例如为什么在协议中直接声明的所需方法与仅在协议扩展中声明的方法(基本上在协议中直接声明的方法是在见证表,因此它们可以被动态调度,而仅在扩展中的不在见证表中,因此任何特定于类型的实现都将丢失,而只能调用协议扩展中的实现。
以下函数使用它来打印其参数的类型(有更好的方法,但这说明了T.Type
和T.self
的作用):
func foo<T>(_ value: T)
let typeOfValue: T.Type = T.self
print("The value, \(value), is of type, \(typeOfValue).")
【讨论】:
感谢您的详细回答。 :] 欣赏! 非常感谢您提供如此详细的回答。以上是关于Swift 5 中的 THE.self 是啥?的主要内容,如果未能解决你的问题,请参考以下文章