【问题标题】:Why not make every Scala class a case class?为什么不让每个 Scala 类都成为案例类呢?
【发布时间】:2016-10-04 12:40:46
【问题描述】:

案例类有一些不错的性能,例如copy, hashCode, toString, Pattern Matching。为什么不让每个 Scala 类都成为案例类?

【问题讨论】:

  • 一个主要原因是你不能有case class to case class继承。
  • @Make42 -- 抱歉,我的回答有误。我已将其删除。会写一个新的。

标签: scala


【解决方案1】:

case class 非常适合保存复杂值,例如实体对象。它们被认为是针对这种情况的,因此它们通过综合您提到的方法并进一步使您的类Serializable 并使用“工厂”方法(除了模式匹配提取器)。

缺点如下:

  • case class 具有的某些属性可能对您正在创建的类不感兴趣:您是否希望在持有数据库连接的对象上使用equals 方法? Serializable 有意义吗?如果是这样,它会安全吗?

  • 所有这些功能都不是免费的:它们需要编译器做一些额外的工作并增加最终的工件大小;如果您不需要 case class 提供的额外功能,为什么还要拥有这些功能?

  • 您不能从 case class 继承到另一个 case class,这可能与您对域建模的方式背道而驰。为什么?简短的回答:平等。您可以找到更长的答案here

【讨论】:

  • “实体对象”通常意味着几乎相反的东西:身份对它很重要的类,因此它不能是案例类。
  • 也许我错了,但我不确定实体对象的身份是否应该绑定在机器上共享相同地址的对象上,而不是来自内在的身份值。如果两个值相同,则它们甚至在联网的计算机上也是如此。
  • 很公平,“不可能”是夸大其词。
【解决方案2】:

案例类具有清晰的语义——data container(更好的 POJO 或 ADT 块,取决于您的背景)。

有时像copyunapply 这样的方法可能具有令人困惑的含义——例如如果字段是可变的。案例类旨在用于“惯用的 scala 风格”,这可能并不适用于任何地方。

最后但并非最不重要的——技术缺点(.class 中的代码更多,要序列化的代码更多,继承问题)。

【讨论】:

  • 什么是“惯用的 scala 风格”?
  • “案例类具有清晰的语义” - 是使用它们的理由,而不是不使用它们;-)。
  • 我不想详细描述什么是“惯用的 scala 风格”,因为这可能会导致无关紧要的质疑圣战。简而言之——避免可变状态,避免副作用,将动作描述为功能的组合。关于第二个问题——有时你不能保证语义,甚至你会破坏它。例如,std 库构建器有一个状态 => 不能是案例类,RedBlackTreecopy 必须注意树的完整性,这超出了copy 的职责范围。
  • @Make42:“案例类具有清晰的语义” - 是使用它们的理由,iff 所讨论的类具有案例类语义!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-12
  • 2012-08-24
  • 2013-02-12
  • 1970-01-01
  • 2011-01-19
  • 1970-01-01
相关资源
最近更新 更多