繁体   English   中英

Swift 4 泛型数组作为泛型类中的参数

[英]Swift 4 generic array as parameter in generic class

我有一个用于测试的匹配器

class GWMatcher<ResultType> {
    let result: ResultType
    let message: String

    init(result: ResultType, message: String) {
        self.result = result
        self.message = message
    }
}

我想添加扩展以将其与数组一起使用。 我希望它像这样:

extension GWMatcher where ResultType == [Equatable] {
    func checkEqual(_ expression: ResultType) {
        XCTAssertEqual(self.result, expression, self.message)
    }
}

但是编译器说:

无法使用类型为([Equatable], Array<Equatable>, String)的参数列表调用XCTAssertEqual

有没有人有想法,是否有可能做这样的事情?

我相信您遇到了 Swift 类型系统的边缘情况。 特别是,通用约束:

extension GWMatcher where ResultType == [Equatable]

应该真正指定为:

extension GWMatcher where ResultType == [T] where T: Equatable

但目前不支持最后一种形式(对于扩展)。 这一点很重要,因为斯威夫特协议符合本身,这将需要忠于[Equatable]如预期的工作(这就是为什么一个具体类型T是必需的)。 我知道,非常棘手......;)

此外,标准Equatable协议只能用作通用约束,因为它具有Self要求(使用关联类型的协议也有类似的行为)。 这种 Swift 限制也可能是罪魁祸首。

解决方法 无论如何,作为一种不太安全的解决方法,请尝试以下操作:

extension GWMatcher {
    func checkEqual<T: Equatable>(_ expression: [T]) {
        guard let result = self.result as? [T] else {
            XCTFail("Expected type \([T].self)")
            return
        }
        XCTAssertEqual(result, expression)
    }
}

这不像您的原始设计那样类型安全,因为它将可用于所有GWMatcher类型,包括那些ResultType未键入为[Equatable]类型。 尽管如此,它应该按预期工作。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM