【问题标题】:Swift 4 generic array as parameter in generic classSwift 4 泛型数组作为泛型类中的参数
【发布时间】:2017-10-03 08:38:45
【问题描述】:

我有一个在测试中使用的匹配器

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&lt;Equatable&gt;, String) 类型的参数列表调用XCTAssertEqual

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

【问题讨论】:

    标签: ios swift generics xctest swift4


    【解决方案1】:

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

    extension GWMatcher where ResultType == [Equatable]
    

    确实应该指定为:

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

    但目前不支持最后一种形式(对于扩展)。这很重要,因为 Swift 协议 符合自身,这需要符合 [Equatable] 的预期工作(这就是需要具体类型 T 的原因)。我知道,非常棘手...... ;)

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

    解决方法。无论如何,作为 less 类型安全的解决方法,请尝试以下方法:

    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] 的类型。不过,它应该可以按预期工作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-03-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多