我可以在 Scala 中定义“方法私有”字段吗?
Posted
技术标签:
【中文标题】我可以在 Scala 中定义“方法私有”字段吗?【英文标题】:Can I define “method-private” fields in Scala? 【发布时间】:2011-05-23 00:05:30 【问题描述】:鉴于这种情况:
object ResourceManager
private var inited = false
def init(config: Config)
if (inited)
throw new IllegalStateException
// do initialization
inited = true
有什么方法可以让inited
以某种方式“私有于init()”,这样我就可以确定这个类中没有其他方法能够设置inited = false
?
【问题讨论】:
另见***.com/questions/1516087 【参考方案1】:取自In Scala, how would you declare static data inside a function?。不要使用方法而是函数对象:
val init = // or lazy val
var inited = false
(config: Config) =>
if (inited)
throw new IllegalStateException
inited = true
在外部作用域(val
)或首次访问(lazy val
)的初始化期间,变量的主体被执行。因此,inited
设置为 false
。最后一个表达式是一个匿名函数,然后分配给init
。以后每次访问init
都会执行这个匿名函数。
请注意,它的行为完全不像一个方法。 IE。在没有参数的情况下调用它是完全有效的。然后它的行为就像一个带有下划线 method _
的方法,这意味着它只会返回匿名函数而不会抱怨。
如果出于某种原因,您确实需要方法行为,您可以将其设为private val _init = ...
并从公共def init(config: Config) = _init(config)
调用它。
【讨论】:
好答案。我正在考虑这个问题,但我并没有从def
跳转到 val
以使其发挥作用。
相当聪明,但也太聪明了。
作为后续,包括仅在初始化代码中分配的 set-once 变量,请参阅此解决方案:***.com/questions/4404024/…【参考方案2】:
以下内容绝对算得上是值得的更多麻烦,但确实满足规格。否则没有办法这样做
object ResourceManager
private object foo
var inited = false
def doInit(config:Config)
if (inited)
throw new IllegalStateException
// do initialization
inited = true
def inner(config: Config)
foo.doInit(config)
【讨论】:
【参考方案3】:如果您只想确保调用一次init
,请执行以下操作:
lazy val inited =
// do the initialization
true
def init = inited
这样初始化代码将只运行一次,但是您运行init
的多次,并且inited
无法获得另一个值,因为它是val
。唯一的缺点是,只要查询 inited
的值,初始化就会运行...
【讨论】:
这里的问题是他不想被初始化,但是在正确初始化之前可以检查它的值。【参考方案4】:创建一个只能从 false 变为 true 的“trapdoor”对象会更容易:
object ResourceManager
object inited
private var done = false
def apply() = done
def set = done = true
def init(config: Int)
if (inited())
throw new IllegalStateException
// do initialization
inited.set
【讨论】:
但是 inited.set 不能被其他方法调用吗? 您说“确保没有其他方法可以设置inited = false
”。在我的示例中,any 方法无法使用 set
将其设置为 false。以上是关于我可以在 Scala 中定义“方法私有”字段吗?的主要内容,如果未能解决你的问题,请参考以下文章
在 java/scala 中生成 ecdsa 32 字节私钥