3

如何在 Scala 中在主构造函数中定义局部变量?

我需要从Scala for the impatient书中解决这个练习:

编写一个 Person 类,其主构造函数接受包含名字、空格和姓氏的字符串,例如 new Person("Fred Smith")。提供只读属性 firstName 和 lastName。主构造函数参数应该是 var、val 还是普通参数?为什么?

现在我的解决方案如下所示:

class Person(firstLast: String) {
  private[this] val firstLastAsArr = firstLast.trim.split(" ")

  val firstName = firstLastAsArr (0)
  val lastName = firstLastAsArr (1)
}

如何将firstLastAsArr变量可见性限制在主构造函数范围(现在它具有类范围)?

4

5 回答 5

5

一种解决方案是立即初始化firstNamelastName从而允许firstLastAsArr在初始化块内变成本地临时值:

class Person(firstLast: String) {
  val (firstName, lastName) = {
    val firstLastAsArr = firstLast.trim.split(" ")
    (firstLastAsArr(0), firstLastAsArr(1))
  }
}
于 2013-06-20T10:22:15.597 回答
4

这不是一个普遍的答案,但你可以用这种特殊的方式写:

  val Array(firstName, lastName) = firstLast.trim.split(" ")
于 2013-06-20T10:25:28.840 回答
2

您并不严格需要中间变量:

class Person(firstLast: String) {
  val (firstName, lastName) =
    firstLast.trim.split(" ") match {case Array(first, last) => (first, last)}
}

但是,如果您的转换从firstLastfirstName并且lastName增长得更长,例如,因为您检查是否确实有一个名字和一个姓氏,那么我会将整个拆分业务封装在一个专用方法中:

class Person(firstLast: String) {
  val (firstName, lastName) = split(firstLast)

  private def split(firstLast: String): (String, String) = {
    val firstLastAsArr = firstLast.trim.split(" ")
    ...
    (first, last)
  }
}
于 2013-06-20T10:24:44.757 回答
1

构造函数中的模式匹配工作得很好,但您应该考虑将此类逻辑从构造函数移至工厂方法:

case class Person(firstName: String, lastName: String)
object Person{
  def apply(firstLast: String) = {
    val firstLastAsArr = firstLast.trim.split(" ")
    new Person(firstLastAsArr(0), firstLastAsArr(1))
  }
}

val p = Person("My Title")
于 2013-06-20T10:46:00.547 回答
0

主构造函数中的模式处理效果很好

  class Person(_fullName:String) {
    val (firstName, lastName) =  _fullName.split(" ") match {
      case Array(x:String, y:String, _*) => (x,y)
      case _ => (null,null)
    }
  }

请参阅我的 github 以获取完整答案 https://github.com/BasileDuPlessis/scala-for-the-impatient/blob/master/src/main/scala/com/basile/scala/ch05/Ex07.scala

于 2014-05-21T08:15:11.187 回答