是否有可能以及如何让 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 只能设置一次?的主要内容,如果未能解决你的问题,请参考以下文章

php怎么样判断是不是有这个变量

如何用C#实现让一个用户只能登录一次这个功能

jmeter如何设置登录接口只调用一次以及遇到的问题:cookie参数放在消息头headers里面?

在bash中取消设置变量检查

thinkphp怎么让循环volist除去最后一次

您如何设置安全性以便用户只能在 Sitecore 中查看/编辑他们的项目?