我在为NodeSeq编写自定义匹配器时遇到了问题:
private def matchXML(expected: NodeSeq) = new Matcher[NodeSeq] {
def apply(left: NodeSeq): MatchResult = MatchResult(left xml_== expected,
"XML structure was not the same (watch spaces in tag texts)",
"XML messages were equal")
}
这编译,但下面的代码:
val expected : NodeSeq = ...
val xml : NodeSeq = ...
xml should matchXML(expected)
导致:
error: overloaded method value should with alternatives:
(beWord: XMLStripDecoratorTests.this.BeWord)XMLStripDecoratorTests.this.ResultOfBeWordForAnyRef[scala.collection.GenSeq[scala.xml.Node]] <and>
(notWord: XMLStripDecoratorTests.this.NotWord)XMLStripDecoratorTests.this.ResultOfNotWordForAnyRef[scala.collection.GenSeq[scala.xml.Node]] <and>
(haveWord: XMLStripDecoratorTests.this.HaveWord)XMLStripDecoratorTests.this.ResultOfHaveWordForSeq[scala.xml.Node] <and>
(rightMatcher: org.scalatest.matchers.Matcher[scala.collection.GenSeq[scala.xml.Node]])Unit
cannot be applied to (org.scalatest.matchers.Matcher[scala.xml.NodeSeq])
xml should (matchXML(expected))
这意味着什么?
答案 0 :(得分:8)
为什么不能进行类型检查:
类型检查器按以下方式工作。
xml.should(matchXML(expected))
should
不属于NodeSeq
,因此编译器会尝试为xml
ShouldMatcher
找到implicit conversion。
“Scala编程”一书指出这种隐式转换应该是最具体的:“通过Scala 2.7,这是故事的结尾。无论何时 应用了多个隐式转换,编译器拒绝选择 它们之间。 ...... Scala 2.8放松了这个规则。如果其中一个可用 转换比其他转换更严格,然后转换 编译器将选择更具体的一个。 ......一个隐含的转换 如果下列之一适用,则比其他更具体: 前者的参数类型是后者的子类型。 ..“
由于NodeSeq
扩展了Seq[Node]
,因此以下函数
convertToSeqShouldWrapper[T](o : scala.GenSeq[T]) : SeqShouldWrapper[T]
因此是所有其他人中最具体的一个。
该程序被重写为:
`convertToSeqShouldWrapper(xml).should(matchXML(expected))`
其中convertToSeqShouldWrapper(xml)
是SeqShouldWrapper[T]
T = GenSeq[Node]
。
来自should
的方法SeqShouldWrapper
接受Matcher[T]
,它是T => MatchResult
类型的函数。因此,它接受Matcher[GenSeq[Node]]
。
由于T
出现在箭头的左侧,匹配器在T
中不是covariant,而是逆变。 NodeSeq
是GenSeq[Node]
,因此Matcher[GenSeq[Node]]
是Matcher[NodeSeq]
,而不是相反。这解释了上述错误,方法should
无法接受Matcher[NodeSeq]
并且需要Matcher[GenSeq[Node]]
。
2解决方案
NodeSeq
的所有实例替换为GenSeq[Node]
,以便类型与所有地方匹配。或者,使用转换函数明确地包装xml。
convertToAnyShouldWrapper(xml).should(matchXML(expected))
答案 1 :(得分:-1)
我认为您的matchXML
方法不在范围内。