2014-12-21 8 views
8

Esiste un modo nativo per assicurarsi che una variabile possa essere impostata solo una volta?E 'possibile e come avere var che può essere impostato solo una volta?

Attualmente, sto usando questo approccio

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] 
} 
+2

È possibile utilizzare un 'lazy val'? Quando viene impostata e utilizzata la variabile? –

+0

No, ho bisogno che l'userIP sia impostato su QUALSIASI punto – Andrey

risposta

1

È possibile creare una variabile costante utilizzando un val. Per esempio:

val a = 0; // Cannot be changed 
var b = 0; // Can be changed 

Vedere questa risposta per maggiori dettagli: https://stackoverflow.com/a/1792207/4380308

Edit:

Un val può essere dichiarata e quindi inizializzato in seguito pure.

val a; 
a = 0; 
+3

Penso che ciò che vuole Andrey sia qualcosa che può avere il suo valore impostato in un secondo momento. –

+0

@ChrisMartin Modificherò la mia risposta, tuttavia un val può essere ancora dichiarato e quindi inizializzato in seguito. –

+0

Voglio dire ... * dopo *. Come, non in quel blocco. –

0

si può provare il seguente:

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 
} 

È possibile utilizzare questo ulteriore tipo:

var singleVal = new varSingleton[Integer] 
singleVal := 12 
singleVal() // returns 12 
singleVal := 13 //IllegalStateException 
4

Non esiste costrutto del linguaggio, ma credo di poter ripulire il codice, almeno.

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

utilizzati:

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

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

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

ho omesso il null considerazione perché codice Scala idiomatica tende a non utilizzare o non null all'esterno della compatibilità Java. Per lo più fingiamo che non esista.

1

Approccio utilizzando pigro:

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 

Per rendere più threadsafe è possibile utilizzare:

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

è possibile utilizzare semplici getter e 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 
                 //| [email protected] 
clientInfo.userIP = "first" 
clientInfo.userIP          //> res0: String = first 

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

io preferisco usare l'opzione che il valore direttamente per evitare null e NPE. Ovviamente puoi aggiungere la logica necessaria nel setter.

Problemi correlati