Reputation: 2341
Is there a native way to make sure that a variable can only be set once?
Currently, I am using this approach
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]
}
Upvotes: 11
Views: 941
Reputation: 1883
you can use simple getter and 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
I prefer to use Option that the value directly to prevent nulls and NPE. You can of course add what ever logic you need in the setter.
Upvotes: 0
Reputation: 1512
Approach using 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
To make it threadsafe you can use:
def apply(_v: T = ???): T =
synchronized {
v = _v
value
}
Upvotes: 1
Reputation: 30736
There's no such language construct, but I think I can clean up your code, at least.
class SetOnce[A](var toOption: Option[A] = None) {
def set(a: A): Unit = if (toOption.isEmpty) toOption = Some(a)
def get: A = toOption.get
}
Usage:
val x = new SetOnce[Int]
x.toOption // None
x.set(1)
x.get // 1
x.set(2)
x.get // 1
I omitted the null
consideration because idiomatic Scala code tends to not use or consider null
outside of Java compatibility. We mostly pretend that it doesn't exist.
Upvotes: 4
Reputation: 9403
You can try the following:
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
}
You can use this further like:
var singleVal = new varSingleton[Integer]
singleVal := 12
singleVal() // returns 12
singleVal := 13 //IllegalStateException
Upvotes: 0
Reputation: 892
You can create a constant variable by using a val. For instance:
val a = 0; // Cannot be changed
var b = 0; // Can be changed
See this answer for more details: https://stackoverflow.com/a/1792207/4380308
Edit:
A val can be declared and then initialized later as well.
val a;
a = 0;
Upvotes: 0