问题:
您试图name
在它根本不可用的词汇上下文中引用该名称:
val rule1 = new Tenant(name = "Cooper2",
(suggestedFloor: Map[String, Int]) => suggestedFloor(name) != groundFloor)
—name
在此上下文中,不是指name
定义的 within 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]
类型推断器并没有消除重新声明的需要,原因只有比我聪明的人才能详细说明。