【问题标题】:(type: T.Type) makes generic method work whereas without it T cannot be inferred(type: T.Type) 使泛型方法工作,而没有它 T 无法推断
【发布时间】:2021-03-18 08:24:53
【问题描述】:

我正在使用一种简单的方法在我的 Core Data DB 上运行提取请求。我将我的大部分代码都包含在一个协议中,该协议将具有某些内容将扩展的默认实现。我的代码如下:

protocol Modelable {
    func testFetch<T>(type: T.Type) -> [T]?
}

extension Modelable {
    func testFetch<T>(type: T.Type) -> [T]? {
        let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Data"),
            result = try? context.fetch(fetchRequest)
    
        return result as? [T]
    }
}

然后我只是在符合Modelable的结构上调用它

let modelableExtended = ModelableExtended()
print(modelableExtended.testFetch(type: SomeType.self)) // Prints

这段代码的奇怪之处在于,如果我从方法定义和调用它的位置删除type: T.Type,我会收到以下错误:

无法推断通用参数“T”

将类型传递给此方法究竟是如何使其工作的?那不只是方法本身的一个参数,传递与否不应该改变任何东西。

【问题讨论】:

  • 如果你不告诉 Swift T 是什么,result 应该在 result as? [T] 中转换成什么类型​​的数组?
  • 我对你所说的有点困惑,但我想说的是,如果我省略了 type: T.Type 的 testFetch() 的参数,它会抛出 could not be inferred 错误而如果我包含该属性,它将转换为我传入的类型。我不明白该参数如何指示 T 的类型
  • 对,SomeType.self 的类型为 SomeType.Type。您将SomeType.Type 传递给需要T.Type 的方法,因此T 现在由SomeType 限定。没有其他信息或其他类型参数,所以我们完成了。 T 被推断为它的唯一绑定 - SomeType。您还想要更多的实现细节吗?
  • 而且 .... 如果你没有这个参数,那么 T 没有被绑定(你会得到错误)。我发布了一个答案,显示了如何尝试绑定返回类型而不是 [T]?
  • This 拥有您需要的所有详细信息。 IMO,如果您只是想“围绕泛型”,那么我建议您不要深入实施。 “这是一个可以接受任何T.Type的方法。你给它一个SomeType.Type。啊,TSomeType!”不用担心编译器是怎么做的,只要在自然语言级别上对您有意义,您就可以理解类型推断。

标签: swift generics types


【解决方案1】:

如果你不想传入类型,你可以这样做

let modelableExtended = ModelableExtended()
let result: [SomeType]? = modelableExtended.testFetch()
print(result)

在某些时候,您必须通过传入一些引用它的参数或通过分配结果来说明T 是什么。

泛型是一种编译时特性。也许您认为它们就像AnyAnyObject 一样,您永远不必说出类型,然后您可以在运行时找出您实际拥有的内容。这不是泛型的工作原理。

泛型让您编写可以使用许多不同类型的代码,但实际运行的代码使用的是从其上下文推断的特定类型。如果无法推断,则代码将无法编译,永远不会运行。

【讨论】:

  • 那么通过引用T.Type Swift 在后台处理以确定实际类型是什么?
  • 编译时间正在发生。当你使用泛型时——你是说——在某个时候——当我实际使用它时,我会告诉你 T 到底是什么。您通常通过提供与模式匹配的参数来执行此操作,以便可以计算出 T。但是,您也可以通过将返回值分配给具有已知类型的变量来实现。
  • @JoeScotto Swift 是一种类型推断语言。你可以说let result: [SomeType] = modelableExtended.testFetch()let result = modelableExtended.testFetch() as [SomeType] 我更喜欢显式设置类型
  • @LeoDabus 但是这在幕后是怎么做的呢?我感到困惑的是,Swift 究竟是如何知道将特定参数推断为 T 的类型的。
  • 您正在显式设置结果类型。同let double: Double = 2
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-27
  • 2017-09-08
  • 1970-01-01
  • 2019-09-06
  • 1970-01-01
相关资源
最近更新 更多