斯威夫特找不到正确的类型

时间:2017-04-17 17:23:39

标签: swift generics hamcrest

我正在尝试使用SwiftHamcrest

我有一个功能

func equalToArray<T, S>(_ vector:Array<S>) -> Matcher<T> {
  let v: Matcher<T> = Hamcrest.hasCount(16)
  return v
}

这会产生错误

Error:(16, 31) 'hasCount' produces 'Matcher<T>', not the expected contextual result type 'Matcher<T>'

SwiftHamcrest有两个hasCount函数

public func hasCount<T: Collection>(_ matcher: Matcher<T.IndexDistance>) -> Matcher<T> 
public func hasCount<T: Collection>(_ expectedCount: T.IndexDistance) -> Matcher<T> 

为什么我的代码抱怨不是它返回所需的相同类型。

作为一个注释,可能是一个不同的问题,我不得不添加Hamcrest。在hasCount方法调用之前,否则它尝试匹配第一个函数

我对类型缺少什么?

1 个答案:

答案 0 :(得分:1)

您的方法equalToArray<T, S>不知道T是一个集合,因此上述通用hasCount(...)方法的结果将无法分配给您的方法v(因为这些结果会将Matcher<T>个实例限制为T:s Collection:s)。即,v对于非约束Matcher<T>属于T类型,这意味着,在编译器的眼中,例如对T.IndexDistanceT的{​​{1}}没有v

如果您向方法的Collection添加T类型约束,则hasCount(...)结果到v的分配应该编译:

func equalToArray<T: Collection, S>(_ vector: Array<S>) -> Matcher<T> {
    let v: Matcher<T> = Hamcrest.hasCount(16)
    return v
}

在一个完美的世界中,编译器可以给我们一个更有说服力的错误信息,比如

  

错误:(16,31)'hasCount'生成'Matcher<T>',其中'T: Collection',   不是预期的上下文结果类型“Matcher<T>

现在,我不知道你打算在这里测试什么,但正如@Hamish指出的那样,你可能真的想要返回Matcher<[S]>并放弃T占位符。例如。使用提供的count参数的vector属性作为hasCount(...)的参数?

func equalToArray<S>(_ vector: Array<S>) -> Matcher<[S]> {
    return hasCount(vector.count)
}

我自己没有使用过Hamcrest,我可能会弄错,但是基于对SwiftHamcrest文档的快速浏览,我相信如上所定义的equalToArray(_:)将构造一个“向量相等”的匹配器(函数的wrt语义) name)仅基于两个向量的计数,在这种情况下,以下断言将成功

let arr1 = ["foo", "bar"]
let arr2 = ["bar", "baz"]

assertThat(arr1, equalToArray(arr2)) // success! ...

但这只是一个署名,因为您没有向我们展示您打算应用equalToArray(_:)方法/匹配器的上下文;也许你只是向我们展示了一个最小的例子,而你自定义匹配器的实际主体更忠实于方法的名称。