从匿名函数引用实例成员

时间:2014-06-26 08:25:20

标签: scala scoping lexical-scope

我正在尝试定义一个实例具有String和函数的类。在函数中使用String参数。

class Tenant(val name: String, exclusion: Map[String, Int] => Boolean)

val rule1 = new Tenant(name = "Baker3",
  (suggestedFloor: Map[String, Int]) => suggestedFloor(name) != topFloor)

val rule1 = new Tenant(name = "Cooper2",
  (suggestedFloor: Map[String, Int]) => suggestedFloor(name) != groundFloor)

在最后一次使用名称时出现错误:not found: value name

我该怎么做?

2 个答案:

答案 0 :(得分:2)

<强>问题:

您正试图在词汇上下文中引用名称name,但它根本不可用:

val rule1 = new Tenant(name = "Cooper2",
  (suggestedFloor: Map[String, Int]) => suggestedFloor(name) != groundFloor)

- name在此上下文中未引用name中定义的Tenant,而是引用name范围内的名称rule1定义,当然它显然不存在。使用此代码,错误将消失,但当然这不是您想要的:

val name = ??? // this is the `name` that gets referenced by the lambda

val rule1 = new Tenant(name = "Cooper2",
  (suggestedFloor: Map[String, Int]) => suggestedFloor(name) != groundFloor)

<强>解决方案:

要解决这个问题,不要在实例化时传入函数,而是使用方法覆盖:

abstract class Tenant(val name: String) {
  def exclusion(suggestedFloor: Map[String, Int]): Boolean
}

val rule1 = new Tenant(name = "Baker3") {
  def exclusion(suggestedFloor: Map[String, Int]) =
    suggestedFloor(name) != topFloor
}

这将创建一个Tenant的匿名子类,其中包含exclusion的“自定义”定义;我想说,这也是Scala中惯用的风格。

或者,您可以使用稍微不同的语义并覆盖不是方法,而是覆盖包含函数的属性;当使用_

与更紧凑的lambda定义形式结合使用时,这将产生更短的语法
abstract class Tenant(val name: String) {
  val exclusion: Map[String, Int] => Boolean
}

val rule1 = new Tenant(name = "Baker3") {
  val exclusion = (_: Map[String, Int])(name) != topFloor
}

不幸的是,类型推理器并没有消除对Map[String, Int]重新声明的需要,因为只有比我聪明的人才能详细说明。

答案 1 :(得分:0)

你需要讨论函数或类声明:

class Tenant(name: String)(exclusion: Map[String, Int] => Boolean = _(name) != topFloor)

现在创建一个实例:

scala> new Tenant("hello")()
res8: Tenant = Tenant@13c3c24f