我对在什么情况下应该使用案例类或遵循最佳实践的常规类有一些误解。我已经了解了这两个类的差异,但无法想象自己推荐用于用例或常规类的现实生活示例。
有人可以向我展示真实的例子并解释为什么建议这样做而不是其他方式吗?
如果您要使用不可变对象编写纯函数式代码,您最好尝试避免使用常规类。 函数式范式的主要思想是数据结构和对它们的操作的分离。 案例类是具有必要方法的数据结构的表示。数据的功能应该在不同的软件实体(例如特征、对象)中描述。
相反,常规类链接数据和操作以提供可变性。这种方法更接近面向对象的范例。
因此,如果出现以下情况,请勿使用 案例类:
但是,在这些情况下,您应该真正考虑代码的风格,因为它可能功能不够。
案例类是带有语法糖的普通类。因此,没有真正的大区别,您可以使用案例类完成您可以使用类完成的所有操作,反之亦然。
案例类只是为您节省了大量需要编写的样板代码。
完美契合,顾名思义,就是在模式匹配与
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 _ => ...
}
hashCode
和equals
。例如,您希望能够将它们用作 Set
或 Map
这是另一个更个人化的偏好:
Set
或 Map
中,但您只有一个实例并且不需要结构相等时,则更喜欢 class Foo(val i: Int)
而不是 case class Foo(i: Int)
,因为您不需要没有可能更昂贵的平等检查。如果1.和2.冲突,您可以手动实现特定案例类功能。例如,为可变的非 case 类提供配套的
apply
方法或模式匹配提取器。
案例类以数据为中心。
与常规课程相比,使用案例课程具有以下优势。
(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 的列。
案例类为您提供“免费”(即,您不必编写)
equals
、hashcode
和toString
,以及伴生对象中的apply
和unapply
的实现。
基本上,您可以将案例类视为命名元组,其字段也被命名。
对于其他任何事情,你最好使用普通的类。
普通类就是Java中的类。它可以包含状态和功能。
案例类就像 Java 中的数据 POJO。保存状态的类,可以被函数使用(通常在其他类中)。
当你在 Java 中实现数据 POJO 时,你应该设置它保存的变量,为它们添加 getter 和 setter,实现 hashcode 和 equals,并且可能实现 toString。
通常情况并没有那么糟糕,因为定义变量后,IDE 可以为您生成所有内容,但如果您更改/添加变量,那么您应该记住更新所有方法。
如果是类,您定义变量(或更好的值),编译器会为您生成所有方法。因此,您可以获得两者,无需样板和更新的功能。
对于 case 类,编译器还会生成更多 Java 中没有也不可能拥有的功能,例如伴生对象中的复制函数和 apply/unapply。
Case 类的工作方式类似于 Java 的记录类和 Lombok 库。您可以节省大量样板代码,例如 getter 和 setter。
简而言之,Scala 中的类非常适合对不可变数据进行建模,并且在处理模式匹配和样板文件缩减时特别有用 因为会自动生成一些样板代码,例如 equals、hashCode 和 toString 方法,以及 copy 和 apply 方法,从而更容易使用它们。