我仍在使用我的ScalaTest FeatureSpec DSL。
我想要given
函数的3个变体。全部取tokens: Any
,然后
一个。稍后执行的块block: => Unit
given("user visits", the[AdminHomePage]) {
// just code
}
B中。稍后使用令牌执行的块block: Any => Unit
given("user visits", the[AdminHomePage]) {
x: Any => x match {
case ("user visits", pageClass:Class[Page]) =>
startPage(pageClass)
}
}
℃。没有块,其中令牌由另一个函数处理
given("user visits", the[AdminHomePage])
现在我定义所有三种方法
def given(tokens: Any) = ...
def given(tokens: Any)(block: Any => Unit) = block(tokens)
def given(tokens: Any)(block: => Unit) = block
编译器认为它们不明确。
ambiguous reference to overloaded definition, both method given in trait GivenWhenThenFeatureSpec of type (tokens: Any)(block: => Unit)Unit and method given in trait GivenWhenThenFeatureSpec of type (tokens: Any)(block: (Any) => Unit)Unit match argument types
如何消除歧义,或者编写一个可以区分块(或缺少)的方法?
答案 0 :(得分:2)
我喜欢上面的@ MachAndy解决方案,除了导入unit2emptyfunction转换,我认为这可能会干扰或覆盖其他类型的错误。
如果您定义以下内容:
object Given {
trait Processor {
def process(tokens: Any)
}
class ProcessorA(block: =>Unit) extends Processor {
def process(tokens: Any) = {
block // execute or store block for later, ignoring tokens
}
}
class ProcessorB(block: Any=>Unit) extends Processor {
def process(tokens: Any) = {
block(tokens) // or store block for later execution
}
}
class ProcessorC extends Processor {
def process(tokens: Any) = {
// do something defaultish with the tokens
}
}
implicit def blockToProcessorA(block: =>Unit) = new ProcessorA(block)
implicit def blockToProcessorB(block: Any=>Unit) = new ProcessorB(block)
implicit val processorC = new ProcessorC
def given(tokens: Any)(implicit p: Processor) = p.process(tokens)
}
然后,你可以简单地说:
import Given._
given("user visits", the[AdminHomePage])
given("user visits", the[AdminHomePage]) {
// some stuff that ignores tokens
}
given("user visits", the[AdminHomePage]) { x: Any =>
x match {
// do something that looks at the tokens
}
}
答案 1 :(得分:1)
我在这里有一个解决方案,但我认为它可以得到增强。
我使用单个given
方法作为条目,隐式提供或不提供正文
def given[A](tokens: A)(implicit block: A => Unit) {
block(tokens)
}
首先, sugar 可以使用Unit
块作为Any => Unit
implicit def unit2emptyfunction(body: Unit): Any => Unit = {
case _ => body
}
为了能够在C情况下工作,我提供了一个默认体来填充什么都不做的block
参数。
implicit val doNothing: Any => Unit = { }
现在您可以这样使用它:
/*
* A case, block is implicitly converted into a A => Unit
* although it doesn't use the argument
*/
given("user visits", the[AdminHomePage]) {
// just code
}
/*
* B case, block is fully provided and thus not implicitly converted
*/
given("user visits", the[AdminHomePage]) {
case ("user visits", pageClass: Class[Page]) =>
startPage(pageClass)
}
// C case, block implicitly provided by doNothing implicit val
given("user visits", the[AdminHomePage])