swift - 为什么泛型类型在调用链的下游不通过约束参与方法重载?
问题描述
Swift 允许通过传入的泛型类型上的约束来重载泛型方法。如果将其与具体类型一起使用,则传入的类型将参与此重载,并且将从该类型推断出约束。
一旦泛型方法通过重载解析委托给另一个泛型方法,就不能再推断约束,而是利用上面已经放置在类型上的约束。
protocol Conformance {}
extension String : Conformance {}
// #1
func baseMethod<T>(_ value: T) {
let isConforming = T.self is Conformance.Type
}
// #2
func baseMethod<T>(_ value: T) where T : Conformance {
let isConforming = T.self is Conformance.Type
}
func delegatingMethod<T>(_ value: T) {
baseMethod(value)
}
func run() {
// Calls #2, isConforming = true
baseMethod(String())
// Calls #1, isConforming = true
delegatingMethod(String())
}
我假设这是存在的,因此无论在何处使用泛型类型,您都可以从调用站点获得足够的类型信息,了解哪些约束适用,但它似乎严重且人为地限制了通过约束重载的效用。
是否有任何已知的解决方法来解决这个奇怪的问题?模仿这一点的东西将非常有用。
解决方案
Swift 允许通过传入的泛型类型上的约束来重载泛型方法。
是的......但要非常清楚,这是一个静态重载,而不是动态覆盖。它基于可以在编译时证明的类型。
func delegatingMethod<T>(_ value: T) {
baseMethod(value)
}
我们现在正在编译它,我们需要将它作为一个具体的静态函数调用(可能是内联的)写入二进制文件。我们知道什么T
?我们对此一无所知T
,因此任何where
子句都会失败。
我们甚至不知道这个函数是如何被调用的,因为调用可能来自另一个编译单元或模块。虽然原则上,它可能具有基于访问级别的不同语义,例如当它是私有的并且所有调用都可以评估时使用一个版本,而当它是公共的时使用另一个版本,这将是一个非常可怕的错误来源。
您所要求的是将delegatingMethod
其关于要进行什么函数调用的决定推迟到运行时。这不是泛型的工作方式。此外,您要求将所有where
子句编码在二进制文件的某个位置,以便可以在运行时对其进行评估。也不是泛型如何工作。这将需要一个比 Swift 想要实现的更动态的调度系统。这并非不可能;它只是一种完全不同的动物,并且阻止了很多优化。
这感觉就像您正在尝试使用协议和泛型重新发明类继承。你不能。它们是不同的解决方案,具有不同的功能。类继承基本上是动态的。协议和泛型基本上是静态的。如果您想要基于特定类型的动态调度,请使用类。
推荐阅读
- php - move_uploaded_file 在 wordpress 文件夹中不起作用
- c - “i%0xff”的结果是什么?
- javascript - js下载div并将meta附加到html
- node.js - 来自 url 的 Mailgun 附件 - 谁在阅读流?
- reactjs - useBaseName 在历史 npm 包中不可用
- php - 每次我在提交表单后刷新页面时,用户都会注册
- wpf - 如何在wpf中使DataGrid的第一行只读
- c++ - 使用 Mingw 构建环境 C++?
- python - 将具有 NaN 的 pandas 数据帧转换为深度 >=2 的嵌套 json
- google-maps - NativeScript Google-Places API --> 如何使用?