我有一个在测试中使用的匹配器
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)
}
}
但是编译器说:
无法使用
XCTAssertEqual
类型的参数列表调用([Equatable], Array<Equatable>, String)
。
有没有人有想法,是否可以做这样的事情?
答案 0 :(得分:1)
我相信你正在遇到Swift类型系统的边缘情况。特别是,通用约束:
extension GWMatcher where ResultType == [Equatable]
应该真正指定为:
extension GWMatcher where ResultType == [T] where T: Equatable
但目前不支持最后一种形式(扩展程序)。这很重要,因为Swift协议不符合自身,这需要对[Equatable]
按预期工作为真(这就是为什么需要具体类型T
)。我知道,因为地狱很棘手......;)
此外,标准Equatable
协议只能用作通用约束,因为它具有Self
要求(使用关联类型的协议也表现相似)。这种斯威夫特的限制也可能归咎于此。
解决方法即可。无论如何,作为 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
不是&#39;输入为[Equatable]
。不过,它应该按预期工作。