如何声明静态全局值并在Scala中定义它们?

yqkkidmi  于 2023-01-30  发布在  Scala
关注(0)|答案(2)|浏览(107)

主要目标

我想在类中使用一些静态值,这样我就不必将它们作为函数参数传递。
我的方法
因为我希望它们是静态的,所以我在伴随对象中声明它们。但是由于某些原因,当我声明它们时,我不能给它们赋值。所以我遵循下面的方法。

case class DemoParams(name: String)

class Demo {
  def foo = {
    println("Demo params name is: ", Demo.demoParams.name) // Works fine
    anotherFoo(Demo.demoParams.name)           // Throws NPE !
  }
  def anotherFoo(someName: String) = {
    // some code
  }
}

object Demo {
  var demoParams: DemoParams = _      // Declare here
  def apply() = new Demo()

  def run = {
    demoParams = DemoParams(name = "Salmon")      // Define here
    val demoObj = Demo()
    demoObj.foo
  }

  def main() = {
    run
  }
}

Demo.main()

我可以打印Demo.demoParams,但令人惊讶的是,当我在集群上运行Spark应用程序时,当我将Demo.demoParams传递给另一个函数时,这会引发NullPointerException。

问题

1.首先,这是声明静态值并在以后定义它们的正确方法吗?我宁愿不使用vars,而使用不可变的vals。有更好的选择吗?
1.其次,您能想到在将Demo.demoParams.name传递给另一个函数时会得到NPE的任何原因吗?

k5hmc34c

k5hmc34c1#

您的代码works fine,并且没有抛出任何东西(在修复了一些编译错误之后)。
但是......别这样,这......很恶心:/
把params作为......嗯......参数传递给类怎么样?

case class Demo(params: DemoParams) {
  def foo() = {
    println("Demo params name is: " + params.name) 
  }
}

object Demo {
  def run() = {
    val demoParams = DemoParams(name = "Salmon") 
    val demoObj = Demo(demoParams)
    demoObj.foo()
  }
}
hc2pp10m

hc2pp10m2#

不确定这是不是最好的替代方法,但可以考虑使用trait,这样可以避免使用var,从而使您仍然停留在FP区域:

case class DemoParams(name: String)

trait Demo {
  val demoParams: DemoParams
}

然后只需在需要的地方定义它,它就可以随时用途:

object MainApp extends App {
  val demoObj = new Demo {
    override val demoParams: DemoParams = DemoParams(name = "Salmon")
  }

  println("Demo params name is: ", demoObj.demoParams.name) // (Demo params name is: ,Salmon)
  anotherFoo(demoObj.demoParams.name) // Salmon

  def anotherFoo(name: String): Unit = println(name)
}

关于第二个问题,没有实际代码,只能猜测(这个示例代码不会抛出NPE)。可能是您在使用它时没有事先定义它,因为var demoParams: DemoParams = _只是将demoParams初始化为引用类型DemoParams的默认值,在本例中为null,当你试图访问null对象的name值时,你会得到NPE,这就是为什么不鼓励使用var

相关问题