我有一个带有一堆实用程序方法的Scala对象,每个方法都使用一个隐式方法参数 s
object MyObject {
def a(implicit s:String) = ???
def b(implicit s:String) = ???
def c(implicit s:String) = ???
}
Run Code Online (Sandbox Code Playgroud)
我不喜欢implicit s:String在每个参数列表中需要这个的事实.有没有办法只设置s一次变量(即首次访问对象时).对于一堂课,我会做这样的事情:
class MyClass(implicit s:String) {
def a() = ???
def b() = ???
def c() = ???
}
Run Code Online (Sandbox Code Playgroud)
简短的回答是"不,你不能".
为什么?因为s它不是变量,所以它是一个参数.因此它不会在运行时(例如,在第一次加入时)设置,而是在编译时解析(因为它是隐式的).
当您编写MyObject.a代码的一部分时,编译器将检查在当前作用域中是否存在隐式String定义,并将使用该定义s.
如果您a在代码的另一部分中使用它,它将使用该范围中的隐式定义,这可能完全不同.
所有这些都在编译时验证,因此它与在运行时访问方法的时间无关(尽管访问它们时可能会更改运行时值s,如果您有可变的含义,应该避免).
如果您总是希望使用相同的定义s,为什么不简单地将此定义放在您的对象中?或者将其作为隐式导入:
object MyObject {
implicit def myImplicitString: String = ??? //first possibility
import MyImplicits.stringImplicit //second possibility, if stringImplicit is indeed defined as implicit
}
Run Code Online (Sandbox Code Playgroud)
底线是,如果您不想传递隐式as参数,则需要将其放在范围内,并且由于范围是a object,因此它必须始终相同.
但是,使用a有class什么问题?它可以为您提供所需的内容(避免重复隐式参数),而无需更改您的调用(只需使用new MyClass().a代替MyObject.a,或者即使MyCaseClass().a您将其定义为a case class).如果对象中有其他字段,则可以始终将它们放在类的伴随对象中,以最大限度地减少实例化时的开销.