以下Swift代码:
class Workflow<ItemClass: Hashable> {
var block: (ItemClass -> Int)?
init() {}
}
protocol ProtocolX {
typealias ItemClass
func foo(x: ItemClass) -> Int
}
func test<Y: ProtocolX, ItemClass: Hashable>(protX: Y, x: ItemClass) {
let workflow = Workflow<ItemClass>()
workflow.block = { (x: ItemClass) in
return protX.foo(x)
}
}
失败,并出现以下编译器错误:
Cannot invoke 'foo' with an argument list of type '(ItemClass)':
Expected an argument list of type '(Self.ItemClass)'
在代码段
return protX.foo(x)
中。这似乎是一个人为的例子,但与我遇到的一个现实问题相比,它有所减少。
如果我尝试遵循错误消息中的建议,我将得到:
'Self' is only available in a protocol or as the result of a method in a class;
did you mean 'Test'?
我怎样才能进行类型检查?
最佳答案
您没有给编译器任何理由相信函数Workflow.ItemClass
中ProtocolX.ItemClass
与test(_:x:)
的类型相同。如果您打算要求ItemClass
函数的test
类型参数与该函数内的ProtocolX.ItemClass
相同,则可以告诉编译器要求它,如下所示:
func test<Y: ProtocolX, ItemClass: Hashable where Y.ItemClass == ItemClass>(protX: Y, x: ItemClass) {
let workflow = Workflow<ItemClass>()
workflow.block = { (x: ItemClass) in
return protX.foo(x)
}
}
但是,您可以完全消除单独的
ItemClass
参数:func test<Y: ProtocolX where Y.ItemClass: Hashable>(protX: Y, x: Y.ItemClass) {
let workflow = Workflow<Y.ItemClass>()
workflow.block = { (x: Y.ItemClass) in
return protX.foo(x)
}
}