第一个例子
func foo<T>(_ t: T) -> String {
return bar(t)
}
func bar<T>(_ t: T) -> String {
return "Other"
}
func bar<T: StringProtocol>(_ t: T) -> String {
return "String"
}
foo("") // "Other" // Why not "String"?
bar("") // "String"
bar(1) // "Other"
第二个例子(更复杂)
第一个例子可以通过类型检查解决,但在这个例子中是不可能的。
func foo<T>(_ t: (T) -> String) -> String {
return bar(t)
}
func bar<T>(_ t: (T) -> String) -> String {
return "Other"
}
func bar<T: StringProtocol>(_ t: (T) -> String) -> String {
return "String"
}
foo { (string: String) -> String in return "" } // Other // Why not "String"?
bar { (string: String) -> String in return "" } // String
bar { (int: Int) -> String in return "" } // Other
超载是静态解决的。因为T内部的foo()是不受约束的,所以它用无约束的T来选择bar()的重载。有没有解决方法?
答案 0 :(得分:0)
根据当前的Swift实现,该函数更专业,意味着它具有约束,这些约束是另一个重载函数的约束的超集;重载将选择更专业的功能。
所以,除了让foo
符合StringProtocol
之外,我无法想到更好的选择。
关于为什么没有更好的黑客,我想引用Swift documentation,它讨论了如何解决嵌套或更专业的泛型类型。:
这相当于运行时重载分辨率,这可能是理想的, 但也有缺点,例如运行时故障的可能性 由于模棱两可和执行如此昂贵的成本 在这些呼叫站点进行操作。当然,这个成本可以减轻 通过上面提到的专业化在热泛型函数中。
我们目前的建议是静态决定哪个功能 被调用(基于C ++中使用的类似的部分排序规则), 并避免运行时重载决议。如果这证明是繁重的,我们可以 稍后重新审视决定。
答案 1 :(得分:0)
谈论工作。 你可以这样做。
func foo<T>(_ t: T) -> String {
if let str = t as? String {
return bar(str)
}
return bar(t)
}
func bar<T>(_ t: T) -> String {
return "Other"
}
func bar<T: StringProtocol>(_ t: T) -> String {
return "String"
}
再说起工作。
func foo<T>(_ t: @escaping (T) -> String) -> String {
if let clsr = t as? (String) -> String {
return bar(clsr)
}
return bar(t)
}
func bar<T>(_ t: (T) -> String) -> String {
return "Other"
}
func bar<T: StringProtocol>(_ t: (T) -> String) -> String {
return "String"
}