当没有任何参数提供通用类型时,我该如何调用一个通用的Swift函数?

4
下面的代码可以在Swift REPL中编译通过:
var m: [String:AnyObject] = [:]
func f<T: AnyObject>(s: String) {
    m[s] = T.self
}

然而,如果我天真地尝试调用f(),这样做:
let s: String = "foo"
class Foo {}
f<Foo>(s)

I get this error:

repl.swift:7:1: error: cannot explicitly specialize a generic function
f<Foo>(s)
^
repl.swift:7:2: note: while parsing this '<' as a type parameter bracket
f<Foo>(s)
 ^

如果我不进行“显式特化”尝试……

f(s)

Swift判断我正在尝试做一些更奇怪的事情,然后我收到了以下信息:

repl.swift:7:1: error: cannot convert the expression's type 'String' to type '()'
f(s)
^~~~

同时,如果我定义一个新函数g()如下:
func g<T: AnyObject>(s: String, t: T) {
    m[s] = T.self
}

并传入一个虚拟的Foo实例:

g(s, Foo())

它很好地工作了:

> m
$R0: [String : AnyObject] = {
  [0] = {
    key = "foo"
    value = {
      instance_type = {}
    }
  }
}

那么Swift让我定义f()的原因是什么?一旦定义了,有没有任何方法来调用它?


补充说明: 我知道也可以明确指定类型来定义一个函数 h<T: AnyObject>(s: String, t: T.Type)。我觉得值得质疑的是Swift允许我定义隐式版本。


仅供记录,另一个解决方法是返回 T。例如:func g<T: AnyObject>(s: String) -> T {...} 现在通过将其转换为 func(s) as Foo,我们不成熟的 Swift 编译器将推断出它的类型,因此无需显式传递它 :( - nacho4d
无法显式地特化一个通用函数。 - nacho4d
这个人也遇到了同样的问题 https://twitter.com/dangerdave/status/490385202170982401 - nacho4d
错误已报告 [rdar://20583619] (http://www.openradar.me/radar?id=6185198710423552) - nacho4d
1个回答

4
与其他语言不同,您不能使用以下语法显式指定通用类型:
f<Foo>(s)

实际类型是通过参数或返回类型推断得出的。在您的情况下,您没有提供一种让类型推断确定 T 是什么的方法。遗憾的是,我不知道如何使用该函数。

我的建议是显式传递 T 的类型:

func f<T: AnyObject>(s: String, type: T.Type) {
    m[s] = type
}

...

f(s, Foo.self)

我已经知道那是一个选项了,但还是谢谢。我的真正问题是为什么Swift让我声明更简洁的形式,以及苹果公司希望我如何调用它。 - David Moles
1
那可能就属于“bug”类别了;-) - Antonio
2
同意;或者至少“是的,有可能编写代码而不会得到错误提示,但实际运行结果与预期不符。” 如果编译器能够捕捉到这种可能性就更好了,但它并没有。这并不意味着 Swift 希望你这样做,就像它不希望你取消引用 nil Optional 一样,尽管它允许这样做。 - Rob Napier
1
我不确定这是一个好的比较。通常情况下,编译器无法在编译时知道 Optional 是否为 nil。(偶尔会有这种情况,我期望一个好的、成熟的 IDE 可以通过静态分析检测到并警告我。)在这里,我们谈论的不是代码没有按照我的预期执行,而是(据我所知)代码根本就不可能执行任何操作。 - David Moles

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接