I have a Scala object with a bunch of utility-methods, each method makes use of an implicit method parameter s
object MyObject {
def a(implicit s:String) = ???
def b(implicit s:String) = ???
def c(implicit s:String) = ???
}
I don't like that fact that I need this implicit s:String
in each parameter list. Is there a way to set the variable s
only once (i.e. when object is first accessed). For a class I would do something like this:
class MyClass(implicit s:String) {
def a() = ???
def b() = ???
def c() = ???
}
Short answer is "No you can't".
Why? Because s
is not a variable, it's a parameter. So it is not set at some point at runtime (say, on first accession), but resolved (because it is implicit) at compile time.
When you write MyObject.a
in a part of your code, the compiler will check if, in the current scope, there is an implicit String
definition, and will use that definition for s
.
If you then use a
in another part of your code, it will use the implicit definition in that scope, which may very well be different.
All this is verified at compile-time, so it is not related to when the methods are accessed at runtime (although when they are accessed may change the runtime value for s
, if you have mutable implicits, which should be avoided).
If you always want to use the same definition for s
, why not simply put this definition in your object? Or import it as an implicit:
object MyObject {
implicit def myImplicitString: String = ??? //first possibility
import MyImplicits.stringImplicit //second possibility, if stringImplicit is indeed defined as implicit
}
The bottom line is, if you don't want to pass the implicit as parameter, you need to have it in scope, and since your scope is an object
, it must always be the same.
However, what's wrong with using a class
? It gives you what you want (avoiding to repeat the implicit parameter) without changing much your calls (just use new MyClass().a
instead of MyObject.a
, or even MyCaseClass().a
if you define it as a case class
). If you have other fields in your object, you can always put them in a companion object to your class, to minimize the overhead at instantiation.