这是我的示例代码:
protocol P {
}
protocol B {
associatedtype ID: P
}
class MyClass: B {
enum ID: P {
case one
case two
}
}
func process<T: B>(_ value: T.ID) {
// do something
}
process(MyClass.ID.one) // Compile Error: cannot convert value of type 'MyClass.ID' to expected argument type '_.ID'
如您所见,我使用参数定义了一个泛型函数,该参数的类型是泛型类型 T 的关联类型。我怎么称呼这个功能?我想使用 MyClass.ID.one 作为参数,但编译器会发出以下警告:
cannot convert value of type 'MyClass.ID' to expected argument type '_.ID'
答案 0 :(得分:6)
从T
开始MyClass.ID
并退回T.ID
MyClass
开始,Swift似乎从调用中推断T
有问题。
如果您更改函数以采用类型为T
的其他参数,则代码会编译并运行正常:
func process<T: B>(_ value: T.ID, _ workaround : T) {
// do something
}
let workaround = MyClass()
process(MyClass.ID.one, workaround)
Swift设计师可以通过两种方式解决这个推理问题:
T
。看来他们决定使用Swift 4进行第二种方法,因为原始函数无法编译,发出以下错误:
函数签名中未使用泛型参数
'T'
更好的解决方法是使用Java风格的方法传递类型而不是实例:
func process<T: B>(_ value: T.ID, _ workaround: T.Type) {
// do something
}
...
process(MyClass.ID.one, MyClass.self)
答案 1 :(得分:0)
dasblinkenlight为您当前实施无效的原因提供了一个很好的答案。如果决定的解决方案是简单地找到另一种方法来实现这个功能,那么我会选择一个不太苛刻的解决方案:
extension B {
static func process(_ value: Self.ID) {
//do stuff
}
}
MyClass.process(.one)
这利用了通过协议扩展Self
可实现的更灵活的类型推断。