2014-12-21 18 views
8

Bir değişkenin yalnızca bir kez ayarlanabildiğinden emin olmanın doğal bir yolu var mı?Mümkün ve yalnızca bir kez ayarlanabilecek var var mı?

Şu anda, bu yaklaşımı

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

Bir "tembel val" kullanabilir misiniz? Değişkeniniz ne zaman ayarlanır ve kullanılır? –

+0

Hayır, HERHANGİ bir noktada – Andrey

cevap

1

kullanıyorum Bir val kullanarak sabit değişkeni oluşturabilirsiniz. Örneğin:

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

fazla ayrıntı için bu yanıta bakın: https://stackoverflow.com/a/1792207/4380308

Düzenleme:

bir val sonra hem başlatıldı sonra ilan edilebilir.

val a; 
a = 0; 
+3

olarak ayarlanması gereken kullanıcı IP'sine ihtiyacım var. Andrey'nin istediği şeyin, daha sonra değerine ayarlanmış bir şey olduğunu düşünüyorum. –

+0

@ChrisMartin Cevabımı düzenleyeceğim, ancak bir değer yine de ilan edilip daha sonra başlatılabilir. –

+0

Demek istediğim ... * daha sonra *. Sanki o blokta değil. –

0

Aşağıdaki deneyebilirsiniz:

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 
} 

kullanabilirsiniz Bu ayrıca gibi:

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

Orada böyle bir dil oluşumu, ama ben kodunuzu temizlemek düşünüyorum, en azından.

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

Kullanımı: deyimsel Scala kodu kullanmak veya Java uyumluluk null dışında düşünmüyoruz eğilimindedir çünkü

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

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

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

Ben null dikkate atlanmış. Biz çoğunlukla var olmadığını iddia ediyoruz. Tembel kullanarak

1

Yaklaşım: Ben Seçenek kullanmayı tercih

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 

:

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

basit alıcı ve ayarlayıcı kullanabilirsiniz: kullanabilirsiniz ÅŸan

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 

bunu yapmak için null ve NPE'yi doğrudan önlemek için bu değer. Tabii ki setterde ihtiyacınız olan mantığı ekleyebilirsiniz.

İlgili konular