Scala的case class和class有什么区别?

493

我在谷歌搜索中寻找“case class”和“class”之间的区别。大家都提到,当你想对类进行模式匹配时,请使用“case class”。否则请使用类,并提及一些额外的好处,如等式和哈希码重写。但这些是使用“case class”而不是“class”的唯一原因吗?

我猜这个特性在Scala中应该有一些非常重要的理由。有什么解释或有没有资源可以学习更多关于Scala case classes的知识?

17个回答

4

与类不同,案例类仅用于保存数据。

案例类对于数据中心应用程序非常灵活,这意味着您可以在案例类中定义数据字段,并在伴生对象中定义业务逻辑。通过这种方式,您将数据与业务逻辑分开。

使用copy方法,您可以从源继承任何或所有所需属性,并随意更改它们。


4

没有人提到case class伴生对象有一个tupled定义,它有一种类型:

case class Person(name: String, age: Int)
//Person.tupled is def tupled: ((String, Int)) => Person

我所能找到的唯一用例是需要从元组构建case class,例如:

val bobAsTuple = ("bob", 14)
val bob = (Person.apply _).tupled(bobAsTuple) //bob: Person = Person(bob,14)

您可以直接创建对象来完成相同的操作,而无需使用元组。但是,如果您的数据集以20个元素(即具有20个元素的元组)的元组列表的形式表示,则可能使用元组是更好的选择。


3
我认为所有答案都给出了有关类和 case 类的语义解释。这可能非常相关,但每个 Scala 的新手都应该知道创建 case 类时会发生什么。我写了这篇文章,简要解释了 case 类。
每个程序员都应该知道,如果他们使用任何预先构建的函数,则正在编写相对较少的代码,这使他们能够编写最优化的代码,但权力伴随着巨大的责任。因此,请非常谨慎地使用预构建的函数。
一些开发人员避免编写 case 类,因为它会增加额外的 20 个方法,您可以通过反汇编类文件来查看这些方法。
如果您想检查 case 类中的所有方法,请参考此链接

3

Case class 是可以与 match/case 语句一起使用的类。

def isIdentityFun(term: Term): Boolean = term match {
  case Fun(x, Var(y)) if x == y => true
  case _ => false
}

你可以看到,case后面跟着一个Fun类的实例,其第二个参数是Var。这是一种非常好用和强大的语法,但它不能与任何类的实例一起使用,因此对于case类有一些限制。如果遵守这些限制,则可以自动定义哈希码和相等性。
模糊的短语“通过模式匹配的递归分解机制”就是指“它与case一起使用”。(实际上,跟在match后面的实例与跟在case后面的实例进行比较(匹配),Scala必须将它们都分解,并且必须递归地分解它们所包含的内容。) case类有什么用处?维基百科关于代数数据类型的文章给出了两个很好的经典例子,列表和树。支持代数数据类型(包括知道如何比较它们)是任何现代函数式语言的必备功能。 case类没有什么用处?一些对象具有状态,像connection.setConnectTimeout(connectTimeout)这样的代码不适用于case类。

现在你可以阅读Scala之旅:案例类


2

早先的答案没有提到的一个重要问题是身份。常规类的对象具有身份,因此,即使两个对象在所有字段上具有相同的值,它们仍然是不同的对象。然而,对于case class实例,相等性仅根据对象字段的值定义。


1
  • 案例类定义了一个伴生对象,带有apply和unapply方法
  • 案例类扩展Serializable
  • 案例类定义了equals hashCode和copy方法
  • 构造函数的所有属性都是val(语法糖)

1

case classes 的一些关键特点如下:

  1. case classes 是不可变的。
  2. 您可以在不使用 new 关键字的情况下实例化 case classes
  3. case classes 可以按值进行比较。

以下是从 Scala 文档中获取的 Scala Fiddle 上的示例代码。

https://scalafiddle.io/sf/34XEQyE/0


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接