Scala - vals的初始化顺序 [英] Scala - initialization order of vals

查看:17
本文介绍了Scala - vals的初始化顺序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这段代码可以从文件中加载属性:

I have this piece of code that loads Properties from a file:

class Config {
  val properties: Properties = {
    val p = new Properties()
    p.load(Thread.currentThread().getContextClassLoader.getResourceAsStream("props"))
    p
  }

  val forumId = properties.get("forum_id")
}

这似乎工作正常.

我尝试将 properties 的初始化移动到另一个 val,loadedProperties,如下所示:

I have tried moving the initialization of properties into another val, loadedProperties, like this:

class Config {
  val properties: Properties = loadedProps
  val forumId = properties.get("forum_id")

  private val loadedProps = {
    val p = new Properties()
    p.load(Thread.currentThread().getContextClassLoader.getResourceAsStream("props"))
    p 
   }

}

但它不起作用!(propertiesproperties.get("forum_id") 中为空).

But it doesn't work! (properties is null in properties.get("forum_id") ).

为什么会这样?loadedPropsproperties 引用时不评估吗?

Why would that be? Isn't loadedProps evaluated when referenced by properties?

其次,这是初始化需要非平凡处理的变量的好方法吗?在 Java 中,我会声明它们的 final 字段,并在构造函数中执行与初始化相关的操作.

Secondly, is this a good way to initialize variables that require non-trivial processing? In Java, I would declare them final fields, and do the initialization-related operations in the constructor.

在 Scala 中是否有这种场景的模式?

Is there a pattern for this scenario in Scala?

谢谢!

推荐答案

Vals 按照声明的顺序进行初始化(嗯,准确地说,non-lazy vals 是),所以 propertiesloadedProps 之前被初始化.或者换句话说,当 properties 被初始化时,loadedProps 仍然是 null.这里最简单的解决方案是在properties之前定义loadedProps:

Vals are initialized in the order they are declared (well, precisely, non-lazy vals are), so properties is getting initialized before loadedProps. Or in other words, loadedProps is still null when propertiesis getting initialized. The simplest solution here is to define loadedProps before properties:

class Config {
  private val loadedProps = {
    val p = new Properties()
    p.load(Thread.currentThread().getContextClassLoader.getResourceAsStream("props"))
    p 
  }
  val properties: Properties = loadedProps
  val forumId = properties.get("forum_id")
}

你也可以让 loadedProps 变得懒惰,这意味着它会在第一次访问时被初始化:

You could also make loadedProps lazy, meaning that it will be initialized on its first access:

class Config {
  val properties: Properties = loadedProps
  val forumId = properties.get("forum_id")

  private lazy val loadedProps = {
    val p = new Properties()
    p.load(Thread.currentThread().getContextClassLoader.getResourceAsStream("props"))
    p 
  }
}

使用惰性 val 的优点是您的代码对重构更加健壮,因为仅更改 val 的声明顺序不会破坏您的代码.

Using lazy val has the advantage that your code is more robust to refactoring, as merely changing the declaration order of your vals won't break your code.

同样在这种特殊情况下,您可以将 loadedProps 转换为 def(如@NIA 所建议的那样),因为它只使用一次.

Also in this particular occurence, you can just turn loadedProps into a def (as suggested by @NIA) as it is only used once anyway.

这篇关于Scala - vals的初始化顺序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆