在很多情况下,我发现我需要在函数范围内创建长寿命值,并且不需要将这些数据放在类/对象范围内。
例如,
object Example {
def activeUsers = {
val users = getUsersFromDB // Connects to the database and runs a query.
users.filter(_.active)
}
}
上面,变量users
的范围正确,但每次调用函数activeUsers
时都会执行数据库查询。
为避免这种情况,我可以将变量users
移到函数范围之外:
object Example {
val users = getUsersFromDB // Connects to the database and runs a query
def activeUsers = {
users.filter(_.active)
}
}
但是,它也可以用于其他功能。
否则,我可以创建一个单独的对象来包含该函数:
object Example {
object activeUsers {
val users = getUsersFromDB // Connects to the database and runs a query.
def apply() = {
users.filter(_.active)
}
}
}
但这涉及更多的样板代码,使用另一个对象以及与apply
相关的轻微语法怪异。
答案 0 :(得分:35)
另一种选择是使用闭包:
object Example {
val activeUsers = {
val users = getUsersFromDB
() => users.filter(_.active)
}
}
activeUsers
是Function1[Unit, ...your filter result type...]
类型的变量(或者我们可以将此类型写为(Unit => ...your filter result type...)
,它是相同的),即此变量存储函数。因此,您可以稍后以与功能无法区分的方式使用它,例如activeUsers()
我们用一个代码块初始化这个变量,我们声明变量users
并在匿名函数() => users.filter(_.active)
中使用它,因此它是一个闭包(因为它有一个绑定变量{{1} })。
因此,我们实现了您的目标:(1)users
看起来像一个方法; (2)activeUsers
计算一次; (3)users
适用于每次通话。
答案 1 :(得分:6)
扩展FunctionXX是实现目标的另一种方式;它可能具有提供更好文档的优势。参数类型和返回值类型都在声明的第一行可见:
val activeUser = new Function0[List[String]] {
val users = getUsersFromDB
def apply = users filter (_.active)
}