Scala函数会覆盖lambda参数

时间:2017-07-13 13:26:46

标签: scala methods lambda override

我尝试实现一个暴露单个方法,该方法有3个覆盖,区分输入参数 - 每个lambda类型 - 如下例所示:

//1:
def onAction(actionFn: =>Any) = ???
//2:
def onAction(actionFn: ()=>Any) = ???
//3:
def onAction(actionFn: (SomeEvent)=>Any) = ???

我正在寻找的是能够使用以下三种变体的代码:

//1: This would be used when defining some code inline
onAction { /* using the empty lambda block expression override */ }

//2: This would mainly be used when passing another function definition
onAction(()=> /* using the lambda expression override */ }
onAction(doMyCoolAction}
onAction(doMyOtherCoolAction}
def doMyCoolAction() : Unit = ???
def doMyOtherCoolAction() : Unit = ???

//3: Used when the "event type" is needed
onAction { e=> /* using the lambda expression with parameter */ }

这样的覆盖并不能很好地协同工作,特别是1.)和2.)覆盖不能很好地协同工作...导致编译器推断出哪些功能定义的问题使用。

是否有任何方法/解决方法可以让我完全使用三个示例用法? (不添加额外的"混乱"语法)

注意:我已经为定义单独的" ActionFn"而烦恼不已。从三种不同的lambda类型隐式转换的类......但是没有运气:

def onAction(actionFn: ActionFn) = ???

class ActionFn {
    //....
}

object ActionFn {
    implicit def noArgLambdaBlockToActionFn(fn: =>Any) : ActionFn = ???
    implicit def noArgLambdaToActionFn(fn: ()=>Any) : ActionFn = ???
    implicit def argLambdaToActionFn(fn: (SomeEvent)=>Any) : ActionFn = ???
}

欢迎提出任何见解,谢谢:)

解决方案尝试: "到目前为止的最佳解决方案",给出了使用场景3的错误。):

//1:
def onAction(actionFn: =>Any) = ???
//2:
def onAction(actionFn: ()=>Any)(implicit d: DummyImplicit) = ???
//3:
def onAction(actionFn: (SomeEvent)=>Any)(implicit d: DummyImplicit) = ???

//3: Used when the "event type" is needed
//Error: "missing parameter type onAction({ e=>":
onAction { e=> /* using the lambda expression with parameter */ }

2 个答案:

答案 0 :(得分:3)

=> Any() => Any变体都会删除相同的类型Function0。但是你可以在其中一个函数中添加额外的参数来消除它们之间的歧义,并使其隐含以避免混乱调用站点。标准库中还有一个方便的DummyImplicit权限

object overloads {
  def onAction(actionFn: => Any) = "by-name"
  def onAction(actionFn: () => Any)(implicit d: DummyImplicit) = "lambda"
}

assert(overloads.onAction(1 + 1) == "by-name")
assert(overloads.onAction(() => 2 + 2) == "lambda")

虽然你可能会因为有人搞砸参数类型而搞得有趣,但这就是它的工作原理:

assert(overloads.onAction { (a: Event1, b: Metadata) => a + b } == "by-name")

答案 1 :(得分:1)

您遇到了这些问题,因为()=>Any和{{1}}属于同一类型。

所以没有解决方案。

我建议你以不同的方式命名这些功能或删除其中一个,因为根据你的定义,他们的行为是相同的。