【问题标题】:Cannot convert value of type 'Generic<String>' to expected argument type 'Generic<Any>'无法将 'Generic<String>' 类型的值转换为预期的参数类型 'Generic<Any>'
【发布时间】:2017-01-07 00:03:24
【问题描述】:

我很困惑...我什至不知道编译器认为会发生什么,但我有 90% 的把握这应该是可能的:

class Generic<Type: Any> {

}

protocol Foo {
    func bar(_ baz: Generic<Any>)
}

class SomeFoo: Foo {
    func bar(_ baz: Generic<Any>) {
        print("Got", baz)
    }
}

let someFoo = SomeFoo()
let generic = Generic<String>()

someFoo.bar(generic) // Compile error: Cannot convert value of type 'Generic<String>' to expected argument type 'Generic<Any>'

这里发生了什么,解决方法是什么?当然必须有一些解决方法......

【问题讨论】:

  • 为什么Generic&lt;String&gt; 可以转换为Generic&lt;Any&gt;(String)-&gt;Void 不能转换为 (Any)-&gt;Void。用户定义的泛型类型不支持协变。 en.wikipedia.org/wiki/…
  • 但是String is Any...如果函数接受Any,我给它一个String,它就不会抱怨
  • StringAny,但 (String)-&gt;Void 不是 (Any)-&gt;Void。我的观点是,不能假设这总是有效。某些语言允许您指定它应该工作;当前版本的 Swift 不是其中之一。
  • 为了清楚起见,假设你有一个函数f(_: String) -&gt; Void。然后假设您有func callFunc(_ x: (Any) -&gt; Void)) { x(42) },这是完全有效的代码。如果(String)-&gt;Void 可以转换为(Any)-&gt;Void,你就可以调用callFunc(f),这显然是无效的,因为42 不是字符串。
  • @jtbandes 这是一个很好的答案:D

标签: swift generics compiler-errors swift3


【解决方案1】:

这称为协方差,它不支持 Swift 中的用户类型(我知道的数组除外)。顺便说一句,Objective-C 泛型以某种方式支持协变。
在您的情况下,我会从 2 个选项中进行选择:

  1. 使 bar 函数通用
  2. 创建将被 foo 函数接受的非通用协议,并在您的 Generic 类中实现此协议

【讨论】:

    猜你喜欢
    • 2020-02-04
    • 2021-06-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多