【问题标题】:Swift not finding the correct typeSwift 找不到正确的类型
【发布时间】:2017-04-17 17:23:39
【问题描述】:

我正在尝试使用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 方法调用之前,否则它会尝试匹配第一个函数

类型缺少什么?

【问题讨论】:

  • 看起来您想要返回 Matcher&lt;[S]&gt; 而不是 Matcher&lt;T&gt;(然后只需删除通用占位符 T)。虽然我不确定vector 参数是干什么用的。
  • @Hamish - 这是我想要其他匹配器的简化案例 - 所以是的,此示例中不需要参数更完整的示例是 func equalToArray(_ vector:Array ) -> Matcher { 让 v: Matcher = Hamcrest.hasCount(vector.count) return v }

标签: swift generics hamcrest


【解决方案1】:

您的方法equalToArray&lt;T, S&gt; 不知道T 是一个集合,因此上述通用hasCount(...) 方法的结果将不能分配给您的方法中的v(因为这些结果返回Matcher&lt;T&gt; 实例限制为T:s,即Collection:s)。即,v 的类型为Matcher&lt;T&gt;,用于非约束T,这意味着,在编译器看来,有例如对于v:s 类型的T,没有T.IndexDistance

如果将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&lt;T&gt;' where 'T: Collection', 不是预期的上下文结果类型'Matcher&lt;T&gt;'


现在,我不知道您打算在这里测试什么,但正如 @Hamish 指出的那样,您实际上可能想要返回 Matcher&lt;[S]&gt; 并删除 T 占位符。例如。使用提供的vector 参数的count 属性作为hasCount(...) 的参数?

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

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

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

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

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

【讨论】:

  • 是的,我知道这不是一个很好的向量比较 - 我只是将示例缩减为一个错误,希望理解这一点会对我的其余部分有所帮助 - 但它没有:(
  • 一般来说,我试图将一个数组传递给一个采用 T... 的函数 - 不幸的是不可能 bugs.swift.org/browse/SR-128 所以你回答的第一部分解决了我的问题,但一般问题无法解决 -我需要重写外部库来获取数组:(
  • @Mark 啊是的,这是一个已知的限制,但对于许多用例,您可以通过提供采用 [T] 参数而不是 T... 的重载来解决它(这将是重载你有实现逻辑的地方),并让T... 方法简单地调用后一个重载。请记住,可变参数只是提供给它的函数体中的一个数组。参见例如以this gist 为例。在您的情况下,这种解决方法可能很有用。
  • @dn 是的,但不幸的是,该库已将较低级别的代码设为私有,因此我无法覆盖它。在这种情况下,有另一个库在做类似的事情,它暴露了对数组的调用
  • @Mark 我明白了,这太糟糕了:/
猜你喜欢
  • 2013-06-28
  • 1970-01-01
  • 1970-01-01
  • 2021-04-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多