【问题标题】:Can I define “method-private” fields in Scala?我可以在 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

【问题讨论】:

标签: scala initialization private access-modifiers


【解决方案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 变量,请参阅此解决方案:stackoverflow.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。
    猜你喜欢
    • 2023-04-10
    • 1970-01-01
    • 1970-01-01
    • 2021-05-01
    • 1970-01-01
    • 2013-05-20
    • 1970-01-01
    • 2018-11-12
    • 2019-10-12
    相关资源
    最近更新 更多