我正在尝试编写一个使用模板/泛型类型分派的库,但我不知道Swift中重载解析是如何工作的。(是否有比Swift编程语言更多的技术参考?)
以下内容与我所希望的完全相同:
func f(_ v: String) { print(v) }
func f(_ v: String?) { f(v!) }
func f(_ v: Int) { print(v) }
func f(_ v: Int?) { f(v!) }
f("foo")
f(Optional("bar"))
f(2)
f(Optional(3))
这个代码的工作方式也是一样的:
func g<T>(_ v: T) { print(v) }
func g<T>(_ v: T?) { g(v!) }
g("foo")
g(Optional("bar"))
g(2)
g(Optional(3))
但是,当我编译它时:
func h(_ v: String) { print(v) }
func h(_ v: Int) { print(v) }
func h<T>(_ v: T?) { h(v!) }
h("foo")
h(Optional("bar"))
h(2)
h(Optional(3))
我收到警告了
all paths through this function will call itself
func h<T>(_ v: T?) { h(v!) }
当然,用一个可选的参数执行它会使堆栈失效。
我的第一个理论是,可能泛型不参与非泛型的过载解析,但以下是:
func i<T: StringProtocol>(_ v: T) { print(v) }
func i<T>(_ v: T?) { i(v!) }
i("foo")
i(Optional("bar"))
给出同样的警告,第二次调用就会触发堆栈。
如果v
是Optional(String)
类型的,我甚至不明白如何将v!
传递给期望T?
的泛型。
发布于 2020-12-17 22:25:57
这是因为在您的一般实现中不会发生任何类型推断。您可以通过执行一些可选的强制转换(以避免崩溃)并将其发送到正确的方法来解决这个问题,这种情况无论如何都会自动发生。所以,就像:
func h<T>(_ v: T?) {
if let stringValue = v as? String {
h(stringValue)
} else if let intValue = v as? Int {
h(intValue)
}
}
也许有点违背了目的,但我可以告诉您,作为一个具有多年经验的Swift开发人员,如果您的其余代码是以Swift友好的方式编写的,这种类型的泛型处理不会/不应该在实际的应用程序中经常出现。我想这是基于观点的,但就是这样。
关于这一评论:
如果v是可选的(字符串),我甚至不明白v是怎么回事!可以传递给期望T?的泛型。
根据您的实现,您将声明v: T?
,这意味着v必须是T
类型或nil
类型。因此,v!
只是您(作为一个开发人员),保证v将是T
类型,而不是nil
,如果您错了,程序就会崩溃。
我假设您这样做只是为了学习目的,但这是我在示例代码中注意到的最大的事情--如果要立即使用,那么让方法接受可选参数是没有意义的!强行拆开。
发布于 2020-12-17 23:49:30
我希望更直接地回答泛型是如何工作的,但是Swift的协议和扩展提供了一种不同的方法来进行相同的分派。
protocol H { func h() }
extension String: H { func h() { print(self) } }
extension Int: H { func h() { print(self) } }
extension Optional: H where Wrapped: H { func h() { self!.h() } }
"foo".h()
Optional("bar").h()
2.h()
Optional(3).h()
Optional(Optional(3)).h()
不幸的是,据我所知,这种分派机制不能应用于元组(或函数类型),因为它们不能被扩展。
https://stackoverflow.com/questions/65349037
复制相似问题