何时使用案例类或常规类

问题描述 投票:0回答:8

我对在什么情况下应该使用案例类或遵循最佳实践的常规类有一些误解。我已经了解了这两个类的差异,但无法想象自己推荐用于用例或常规类的现实生活示例。

有人可以向我展示真实的例子并解释为什么建议这样做而不是其他方式吗?

scala
8个回答
68
投票

如果您要使用不可变对象编写纯函数式代码,您最好尝试避免使用常规类。 函数式范式的主要思想是数据结构和对它们的操作的分离。 案例类是具有必要方法的数据结构的表示。数据的功能应该在不同的软件实体(例如特征、对象)中描述。

相反,常规类链接数据和操作以提供可变性。这种方法更接近面向对象的范例。


因此,如果出现以下情况,请勿使用 案例类

  1. 你的类带有可变状态。
  2. 你的课程包含一些逻辑。
  3. 您的类不是数据表示,并且您不需要结构相等。

但是,在这些情况下,您应该真正考虑代码的风格,因为它可能功能不够。


15
投票

案例类是带有语法糖的普通。因此,没有真正的大区别,您可以使用案例类完成您可以使用类完成的所有操作,反之亦然。

案例类只是为您节省了大量需要编写的样板代码。

完美契合,顾名思义,就是在模式匹配

case
中使用案例类。

case class MyCase(name: String, age: Int)

data : List[MyCase] = ...

data foreach { 
    case MyCase(_, age) if age > 21 => println("old enough")
    case MyCase("fred", _ ) => println("Got you")
    case _ => ...
}

13
投票
  1. 当您的类带有可变状态时,不要使用案例类。
  2. 当您想要结构平等时,一定要使用案例类,因为它为您提供适当的
    hashCode
    equals
    。例如,您希望能够将它们用作
    Set
    Map
  3. 的键

这是另一个更个人化的偏好:

  • 当您只需要自动获取器,并且将实例放入
    Set
    Map
    中,但您只有一个实例并且不需要结构相等时,则更喜欢
    class Foo(val i: Int)
    而不是
    case class Foo(i: Int)
    ,因为您不需要没有可能更昂贵的平等检查。

如果1.和2.冲突,您可以手动实现特定案例类功能。例如,为可变的非 case 类提供配套的

apply
方法或模式匹配提取器。


7
投票

案例类以数据为中心。

与常规课程相比,使用案例课程具有以下优势。

(1) 值等价:这意味着两个案例实例可以与它们内部的值进行比较。

scala> case class Time(hours: Int = 0, mins: Int = 0)
defined class Time

scala> val time1 = Time(12, 13)
time1: Time = Time(12,13)

scala> val time2 = Time(11, 12)
time2: Time = Time(11,12)

scala> time1 == time2
res6: Boolean = false

scala> val time3 = Time(10, 11)
time3: Time = Time(10,11)

scala> time1 == time2
res7: Boolean = false

但是其他比较运算符(>, >= <, etc) are not defined.

(2) 不可变字段:线程安全

(3) 自动字段创建: hours 分钟 是 Scala 自动创建的不可变字段。

scala> time1.hours
res9: Int = 12

case 类也用于解析 Spark DataFrame 行,优点是可以通过 case 类的字段名称访问 DataFrame 的列。


5
投票

案例类为您提供“免费”(即,您不必编写)

equals
hashcode
toString
,以及伴生对象中的
apply
unapply
的实现。 基本上,您可以将案例类视为命名元组,其字段也被命名。

对于其他任何事情,你最好使用普通的类。


4
投票

普通类就是Java中的类。它可以包含状态和功能。
案例类就像 Java 中的数据 POJO。保存状态的类,可以被函数使用(通常在其他类中)。

当你在 Java 中实现数据 POJO 时,你应该设置它保存的变量,为它们添加 getter 和 setter,实现 hashcode 和 equals,并且可能实现 toString。
通常情况并没有那么糟糕,因为定义变量后,IDE 可以为您生成所有内容,但如果您更改/添加变量,那么您应该记住更新所有方法。
如果是类,您定义变量(或更好的值),编译器会为您生成所有方法。因此,您可以获得两者,无需样板和更新的功能。
对于 case 类,编译器还会生成更多 Java 中没有也不可能拥有的功能,例如伴生对象中的复制函数和 apply/unapply。


0
投票

Case 类的工作方式类似于 Java 的记录类和 Lombok 库。您可以节省大量样板代码,例如 getter 和 setter。


0
投票

简而言之,Scala 中的类非常适合对不可变数据进行建模,并且在处理模式匹配样板文件缩减时特别有用 因为会自动生成一些样板代码,例如 equalshashCodetoString 方法,以及 copyapply 方法,从而更容易使用它们。

© www.soinside.com 2019 - 2024. All rights reserved.