【问题标题】:Why does Scala have a case object?为什么 Scala 有一个 case 对象?
【发布时间】:2015-09-16 07:32:15
【问题描述】:

它不能用参数初始化,它只会与自己比较(单例)。所以它的equals和hash code函数没有优势。有没有人遇到过觉得有用的案例?

【问题讨论】:

  • “有没有人遇到过……”。呵呵。我笑了。
  • 当你想定义代数数据类型时很有用:gleichmann.wordpress.com/2011/01/30/…
  • 例如:Nonecase object。实际上,当您的 algebraic datatype 的某些实例应该被区分但没有任何参数时,您会使用 case 对象。就像OptionSome(v)case class,但None 只是None 没有状态。为什么case 有用,请参阅:stackoverflow.com/questions/5270752/…
  • akka 中使用了很多 case 对象作为消息,例如 PoisonPillTick 等。
  • @dmitry 请将其添加为答案!

标签: scala


【解决方案1】:

您可以使用 case 对象 作为枚举的替代方法。

详情请见:Case objects vs Enumerations in Scala


该问题的简化示例:

sealed trait Currency {
  def name: String
  def symbol: String
}

case object EUR extends Currency {
  val name = "EUR"
  val symbol = "€"
}

case object USD extends Currency {
  val name = "USD"
  val symbol = "$"
}

优势

  • 这样可以有更多字段(与Enumeration 中的 ID 和名称相比)
  • 如果匹配不完整,编译器会发出警告(在 sealed 类型层次结构的情况下)。

所以这段代码

val ccy: Currency = EUR
ccy match {
  case EUR =>
    println("Euro")
}

会导致

警告:(27, 7) 匹配可能并不详尽。
它会在以下输入上失败:USD
ccy 匹配 {

缺点

  • 没有“按名称获取”方法(@​​987654326@ 提供 withName()
  • 您不能迭代“所有”元素

【讨论】:

    【解决方案2】:

    我认为最重要的区别是case对象可以序列化,而简单的objects不能。

    这使得它们作为 Akka-Remote 的消息非常有用。

    编辑: 正如Rüdiger Klaehn 所指出的,这不是我们从case 关键字中获得的唯一好处。还有:

    • 哈希码实现
    • 一个有用的 toString 实现

    对于额外的课程:

    • 模式匹配优化
    • 具有有用的 applyunapply 实现的伴随对象

    (此列表可能并不详尽!)

    【讨论】:

    • 案例对象也将实现 hashCode 和 toString。所以case object Foo; foo.toString 只会给出 Foo,而object Foo; Foo.toString 会给出类似 Foo$@1bb485e7 的东西(每次运行都不同!)。 hashCode 相同:case 对象的 hashCode 在不同的 JVM 进程中是相同的。
    • 等待一个case关键字不会使类可序列化吧?
    • @Dragonborn 相反:case 关键字创建了一个类/对象Serializable(除其他外)。
    • @Dragonborn 即使在 Scala 2.10.4 中,case class 也是可序列化的。至少你可以用java.io.ObjectOutputStream.writeObject() 序列化case class 的实例。
    猜你喜欢
    • 1970-01-01
    • 2021-02-12
    • 1970-01-01
    • 1970-01-01
    • 2019-07-09
    • 2013-10-16
    • 1970-01-01
    • 2016-10-03
    • 2017-01-31
    相关资源
    最近更新 更多