为 Scala 的对象设置隐式实例变量
Setting implicit instance variable for Scala's object
我有一个带有一堆实用方法的 Scala 对象,每个方法都使用一个隐式方法参数 s
object MyObject {
def a(implicit s:String) = ???
def b(implicit s:String) = ???
def c(implicit s:String) = ???
}
我不喜欢每个参数列表中都需要这个 implicit s:String
。有没有办法只设置变量 s
一次(即第一次访问对象时)。对于 class 我会做这样的事情:
class MyClass(implicit s:String) {
def a() = ???
def b() = ???
def c() = ???
}
简答为 "No you can't"。
为什么?因为 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
}
最重要的是,如果您不想传递隐式参数,则需要将其包含在范围内,并且由于您的范围是 object
,它必须始终相同。
但是,使用 class
有什么问题?它给你你想要的东西(避免重复隐式参数)而不改变你的调用(只需使用 new MyClass().a
而不是 MyObject.a
,甚至 MyCaseClass().a
如果你将它定义为 case class
).如果您的对象中有其他字段,您始终可以将它们放在 class 的伴随对象中,以最大限度地减少实例化时的开销。
我有一个带有一堆实用方法的 Scala 对象,每个方法都使用一个隐式方法参数 s
object MyObject {
def a(implicit s:String) = ???
def b(implicit s:String) = ???
def c(implicit s:String) = ???
}
我不喜欢每个参数列表中都需要这个 implicit s:String
。有没有办法只设置变量 s
一次(即第一次访问对象时)。对于 class 我会做这样的事情:
class MyClass(implicit s:String) {
def a() = ???
def b() = ???
def c() = ???
}
简答为 "No you can't"。
为什么?因为 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
}
最重要的是,如果您不想传递隐式参数,则需要将其包含在范围内,并且由于您的范围是 object
,它必须始终相同。
但是,使用 class
有什么问题?它给你你想要的东西(避免重复隐式参数)而不改变你的调用(只需使用 new MyClass().a
而不是 MyObject.a
,甚至 MyCaseClass().a
如果你将它定义为 case class
).如果您的对象中有其他字段,您始终可以将它们放在 class 的伴随对象中,以最大限度地减少实例化时的开销。