是否有可能以及如何让 var 只能设置一次?
Posted
技术标签:
【中文标题】是否有可能以及如何让 var 只能设置一次?【英文标题】:Is it possible and how to have var that can only be set once? 【发布时间】:2015-02-19 14:30:36 【问题描述】:是否有本地方法来确保变量只能设置一次?
目前,我正在使用这种方法
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]
【问题讨论】:
你能用lazy val
吗?您的变量何时设置和使用?
不,我需要在任何时候设置用户IP
【参考方案1】:
没有这样的语言结构,但我想我至少可以清理你的代码。
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
的考虑,因为惯用的 Scala 代码倾向于在 Java 兼容性之外使用或考虑 null
。我们大多假装它不存在。
【讨论】:
【参考方案2】:使用惰性的方法:
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
【讨论】:
【参考方案3】:您可以使用 val 创建一个常量变量。例如:
val a = 0; // Cannot be changed
var b = 0; // Can be changed
更多详情请查看此答案:https://***.com/a/1792207/4380308
编辑:
可以声明一个 val,然后也可以稍后对其进行初始化。
val a;
a = 0;
【讨论】:
我认为 Andrey 想要的是可以在以后设置其值的东西。 @ChrisMartin 我将编辑我的答案,但是仍然可以声明一个 val,然后稍后再初始化。 我的意思是……稍后。就像,不在那个街区。 考虑到变量的范围,这仍然可以实现。 来自一个完全不同的文件。例如clientInfo.userIP.set(...)
【参考方案4】:
您可以尝试以下方法:
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
您可以进一步使用它:
var singleVal = new varSingleton[Integer]
singleVal := 12
singleVal() // returns 12
singleVal := 13 //IllegalStateException
【讨论】:
【参考方案5】:你可以使用简单的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.***.ClientInfo controllers.***$Clien
//| tInfo@4fccd51b
clientInfo.userIP = "first"
clientInfo.userIP //> res0: String = first
clientInfo.userIP = "second"
clientInfo.userIP //> res1: String = first
我更喜欢直接使用 Option 表示值来防止空值和 NPE。您当然可以在 setter 中添加您需要的任何逻辑。
【讨论】:
以上是关于是否有可能以及如何让 var 只能设置一次?的主要内容,如果未能解决你的问题,请参考以下文章