我可以在 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 字节私钥

在 Scala 中,泛型类型参数可以与 *function* 定义一起使用吗?

成员修饰符知识点

Scala之继承

Scala学习三-面向对象

Scala:是否可以使用宏注释来注释类的构造函数字段? (宏观天堂)