【问题标题】:Scala function overrides with lambda parametersScala 函数用 lambda 参数覆盖
【发布时间】:2017-07-13 21:53:25
【问题描述】:

我正在尝试实现一个公开具有 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 */ }

【问题讨论】:

  • : => Any 扩展为 () => Any。为什么需要这两个重载?选择一个。
  • 好吧,如果我错了,请纠正我,但如果没有 1.) 定义,我不能使用用法示例 1.) - 类似我不能使用用法示例 2.)没有 2.) 定义?

标签: scala methods lambda overriding


【解决方案1】:

=> 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")

【讨论】:

  • 嗯,不错,我似乎更进一步,但现在我遇到了使用场景 3 的问题。) - “缺少参数类型 onAction({ e=>” - 不是确定如何在评论中输入代码,所以我更新了最初的帖子。
  • @user506262 是的,1 与 3 冲突,因为 Scala 无法确定它是 { e: SomeEvent => ??? } 并且应该使用案例 3,还是 { e: SomeOtherEvent => ??? } 并且是案例 1,因此您必须指定每次都显式地在参数上设置事件类型。
  • 感谢您的解释,我想目前的版本已经很好了:)
【解决方案2】:

您有这些问题是因为=>Any()=>Any 是同一类型。

所以没有适合你的解决方案。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-06
    • 1970-01-01
    • 1970-01-01
    • 2011-05-16
    • 1970-01-01
    • 2018-06-20
    • 1970-01-01
    相关资源
    最近更新 更多