以下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.ItemClassProtocolX.ItemClasstest(_: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)
    }
}

10-04 13:58