Scala 是否可能以及如何设置只能设置一次的var?

Scala 是否可能以及如何设置只能设置一次的var?,scala,Scala,是否有一种本机方法来确保变量只能设置一次 目前,我正在使用这种方法 class SetOnceVariable[T] { private var value : T = _ private var initialized = false def apply(_v : T = _) : T = { if (value != null && !initialized) { value = _v initialized = true

是否有一种本机方法来确保变量只能设置一次

目前,我正在使用这种方法

class SetOnceVariable[T]
{
  private var value : T = _

  private var initialized = false

  def apply(_v : T = _) : T =
  {
    if (value != null && !initialized) {
      value = _v
      initialized = true
    }
    value
  }
}

class ClientInfo
{
  val userIP : SetOnceVariable[String] = new SetOnceVariable[String]
}

您可以使用val创建常量变量。例如:

val a = 0; // Cannot be changed
var b = 0; // Can be changed
有关更多详细信息,请参阅此答案:

编辑:

val也可以声明,然后稍后初始化

val a;
a = 0;

您可以尝试以下操作:

class varSingleton[A >: Null <: AnyRef] {
  private[this] var _a = null: A
  def :=(a: A) { if (_a eq null) _a = a else throw new IllegalStateException }
  def apply() = if (_a eq null) throw new IllegalStateException else _a
}

没有这样的语言结构,但我想我至少可以清理你的代码

class SetOnce[A](var toOption: Option[A] = None) {
    def set(a: A): Unit = if (toOption.isEmpty) toOption = Some(a)
    def get: A = toOption.get
}
用法:

val x = new SetOnce[Int]
x.toOption // None

x.set(1)
x.get // 1

x.set(2)
x.get // 1
<>我省略了<代码> null >代码>考虑,因为在java兼容性之外,习惯性Scala代码不使用或考虑<代码> null >代码>。我们通常假装它不存在。

使用lazy的方法:

  class SetOnceVariable[T] {

    private var v: T = _
    private lazy val value: T = v

    def apply(_v: T = ???): T = {
      v = _v
      value
    }
  }

val info = new ClientInfo
println(info.userIP("IP")) // IP
println(info.userIP("IP2")) // IP
println(info.userIP("IP3")) // IP
要使其线程安全,您可以使用:

def apply(_v: T = ???): T =
  synchronized {
    v = _v
    value
  }

您可以使用简单的getter和setter:

class ClientInfo {
  private var _userIP: Option[String] = None
  def userIP: String = _userIP.get
  def userIP_=(value: String): Unit = {
    _userIP = _userIP.orElse(Option(value))
  }
}

val clientInfo = new ClientInfo()                       //> clientInfo : controllers.stackoverflow.ClientInfo controllers.stackoverflow$Clien
                                                        //| tInfo@4fccd51b
clientInfo.userIP = "first"
clientInfo.userIP                                       //> res0: String = first

clientInfo.userIP = "second"
clientInfo.userIP                                       //> res1: String = first

我更喜欢使用选项,该选项直接将该值设置为null和NPE。当然,您可以在setter中添加所需的逻辑。

我认为Andrey想要的是可以在以后设置其值的东西。@ChrisMartin我将编辑我的答案,但是仍然可以声明val,然后在以后初始化。我的意思是。。。稍后。比如,不在那个块中。考虑到变量的范围,这仍然是可以实现的。从一个完全不同的文件。e、 g.
clientInfo.userIP.set(…)
您可以使用
惰性val
吗?什么时候设置和使用变量?不,我需要在任何时候设置userIP
class ClientInfo {
  private var _userIP: Option[String] = None
  def userIP: String = _userIP.get
  def userIP_=(value: String): Unit = {
    _userIP = _userIP.orElse(Option(value))
  }
}

val clientInfo = new ClientInfo()                       //> clientInfo : controllers.stackoverflow.ClientInfo controllers.stackoverflow$Clien
                                                        //| tInfo@4fccd51b
clientInfo.userIP = "first"
clientInfo.userIP                                       //> res0: String = first

clientInfo.userIP = "second"
clientInfo.userIP                                       //> res1: String = first