0

我正在尝试定义一个类,其实例具有一个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)

这给出了最后一次使用 name: 的错误not found: value name

我怎样才能做到这一点?

4

2 回答 2

2

问题:

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

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

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

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]类型推断器并没有消除重新声明的需要,原因只有比我聪明的人才能详细说明。

于 2014-06-26T10:18:40.293 回答
0

您需要对函数或类声明进行柯里化:

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

现在做一个实例:

scala> new Tenant("hello")()
res8: Tenant = Tenant@13c3c24f
于 2014-06-26T08:40:18.513 回答