Scala 初始化那些在运行时字段中更改的正确方法:placeholder/null、None 或零元素?

Scala proper way to initialize ones changed in runtime fields: placeholder/null, None or zero element?

我得到 class 初始化时的值未知的字段。但是之后,在运行时将获取值并将其设置为字段 just ones

我想决定最适合用于该字段的首次初始化。正如我所读,有这样的方法:

  1. 使用占位符 _null [错误的方式]:

    var name: String = _
    var nextUser: User = null
    
  2. 使用None,比我的代码Some(v)[好,但冗长]:

    var name: Option[String] = None
    var nextUser: Option[User] = None
    
  3. 使用 "zero" 元素:

    var name: String = ""
    var nextUser: User = new User()
    
  4. 使用存根:

    var name: String = "undefined"
    var nextUser: User = UndefinedUser
    

我看到 3 个问题:

  1. Some() 获取值是冗长的,任何时候写 .get 或使用 match/case
  2. var用于字段是不好的,它实际上只会按值设置一次,但在运行时
  3. 写出类似updateUser的方法是不好的

现在我在那些字段中使用 None,因为对于某些不在我的库中的类型,没有任何 constructorempty\"zero"值:

class ClassWithLazyFields {

  var name: String = ""
  var age: Int = 0

  //here, after first asignment as `None` i will set it values only one time
  var myThread: Option[Thread] = None
  var nextUser: Option[User] = None
  var myTransformUnit: Option[TransformUnit] = None

  def updateUser(u: User): Unit = {
    nextUser = u
  }
}

//after first asignment as `None` i set nextUser value like that
classInstance.updateUser(userCat)

// bad ".get" in callings
val name = classInstance.myThread.get.name
val hoursToStart = classInstance.myTransformUnit.get.waitTime.hours

// or more verbose match/case
val hoursToStart = classInstance.myTransformUnit match {
  case Some(v) => v.waitTime.hours
  case None => 0
}

有什么可以指教的吗? 我需要类似 lazy var 的东西或任何好的建议。

建议首先避免使用像这样的可变数据结构。

使 class 不可变并将 updateUser 等方法更改为 return 新的更新实例,而不是修改当前实例。

但是如果您必须这样做,Option 是专门为值可能存在或不存在的情况而设计的。 mapgetOrElse 等方法可以轻松(安全)地使用 Option 值,而且开销很小。


例如,这是您安全计算 namehoursToStart:

的方式
val name = classInstance.myThread.fold("NoName")(_.name)
val hoursToStart = classInstance.myTransformUnit.fold(0)(_.waitTime.hours)

如果您想使用多个 Option 值,请像这样使用 for

for {
  thread <- classInstance.myThread
  user <- classInstance.nextUser
  unit <- classInstance.myTransformUnit
} {
  // Code that uses thread, user, and unit
}

仅当所有三个值都不是 None 时才会调用代码。