为什么不对此Swift代码进行类型检查?

时间:2016-02-05 22:14:31

标签: swift generics type-inference

以下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'?

如何才能进行打字检查?

1 个答案:

答案 0 :(得分:1)

您已让编译器无理由相信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)
    }
}