在 `case class` 中有一个 `private` 构造函数字段有意义吗?

Does it make sense to have a `private` constructor field in a `case class`?

我看到一些像这样的 Scala 代码:

case class Team(private val members: List[User]) {
    def removed(member: User): Team = {
        Team(members.filterNot(_ == member))
    }
    def added(member: User): Team = {
        Team(member :: members)
    }
    def allNames: List[String] = members.map(_.name)
}

您可以看到 Team 是一个 case class,但它有一个 private 字段 members。并且在主体中,它有几个方法来构造一个新的Team,还有一个方法allNames导出私有members的一些信息。

我不确定case class的用法是否好,因为我认为case class是一个数据class,我们不应该使用private字段.对于这种情况,我认为正常的 class 就足够了:

class Team(members: List[User]) {
    def removed(member: User): Team = {
        new Team(members.filterNot(_ == member))
    }
    def added(member: User): Team = {
        new Team(member :: members)
    }
    def allNames: List[String] = members.map(_.name)
}

你可以看到我删除了 case,还有 private 因为对于正常的 class,构造函数的字段默认是私有的。

但我不确定是否有任何充分的理由在第一种方法中编写代码。

case classes 中的私有值有点令人惊讶,因为它们并不像您想象的那样私有,如果您认为其他获取该值的方法只是语法糖的话。

特别是,模式匹配将为您提供基础值:

whatever match {
  case Team(members) => println("I can see "+members.mkString)
}

并且该值仍然在平等中发挥作用(即使您无法通过名称获取它),并且您可以使用 copy.

创建具有不同值的副本

有时 private val 用于强制执行 class 的最佳实践,即仅使用模式匹配来获取值(例如,因为您经常想要模式匹配其他东西,这加强了一致性)。有时这表明程序员不理解它是如何工作的,并认为它强制完全无法访问 val。