In many situations I find that I need to create long-living values inside a function's scope, and there is no need for this data to be at class/object scope.
For example,
object Example { def activeUsers = { val users = getUsersFromDB // Connects to the database and runs a query. users.filter(_.active) } }
Above, the variable users
is in the correct scope, but it will execute a database query everytime the function activeUsers
is called.
To avoid this, I could move the variable users
outside the function's scope:
object Example { val users = getUsersFromDB // Connects to the database and runs a query def activeUsers = { users.filter(_.active) } }
But that makes it available to other functions as well.
Else, I could create a separate object to enclose the function:
object Example { object activeUsers { val users = getUsersFromDB // Connects to the database and runs a query. def apply() = { users.filter(_.active) } } }
But this involves more boilerplate code, use of another object and slight syntax oddities related to apply
.
In Scala there are no static methods: all methods are defined over an object, be it an instance of a class or a singleton, as the one you defined in your question.
You can not declare varibale as static inside a method. Inside method all variables are local variables that has no existance outside this method thats why they cann't be static.
Scala classes cannot have static variables or methods. Instead a Scala class can have what is called a singleton object, or sometime a companion object.
Scala is more object-oriented than Java because in Scala, we cannot have static members. Instead, Scala has singleton objects. A singleton is a class that can have only one instance, i.e., Object. You create singleton using the keyword object instead of class keyword.
Another option would be using a closure:
object Example { val activeUsers = { val users = getUsersFromDB () => users.filter(_.active) } }
activeUsers
is a variable of type Function1[Unit, ...your filter result type...]
(or we can write this type as (Unit => ...your filter result type...)
, which is the same), that is this variable stores a function. Thus you may use it later in a way indistinguishable from function, like activeUsers()
We initialize this variable with a block of code where we declare variable users
and use it inside an anonymous function () => users.filter(_.active)
, hence it is a closure (as it has a bound variable users
).
As a result, we achieve your goals: (1) activeUsers
looks like a method; (2) users
is calculated once; and (3) filter
works on every call.
Extending FunctionXX is another way of achieving the goal; it might have an advantage of providing better documentation. Both parameter types and return value type are visible on the first line of the declaration:
val activeUser = new Function0[List[String]] { val users = getUsersFromDB def apply = users filter (_.active) }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With