在 Scala 中将所有类定义为 case 以便让它们的所有参数自动成为属性是否正确?
我开始使用Scala。如果我希望将一个类的参数公开为属性,我应该将其定义为案例类,我的理解是否正确?它不会带来任何副作用吗?
I'm beginning Scala. Am I correct understanding that I should define a class as a case class if I'd like it's arguments to be exposed as properties? Does not it introduce any side effects?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
为案例类生成的样板代码在字节码中具有较小但非零的成本。除了
copy
方法之外,还有hashCode
、equals
和toString
以及伴随对象工厂方法。更重要的是,从案例类派生类是不可取的。从案例类派生案例类确实会带来问题(并且编译器会对您大喊大叫)。特别是,编译器不会生成重写的
copy(...)
方法,因此,如果您尝试复制从案例类派生的案例类,您可能会遇到一些奇怪的失败模式。如果您将案例类保留在任何继承图的叶子中,那就没问题了。
The boilerplate code generated for case classes carries a small but non-zero cost in bytecode. In addition to the
copy
method, there ishashCode
,equals
andtoString
as well as the companion object factory method.More significant is the fact that it is inadvisable to derive classes from case classes. Deriving a case class from a case class really invites problems (and the compiler will yell at you). In particular, no overriding
copy(...)
method is generated by the compiler, so you can get some odd failure modes if you try to copy a case class derived from a case class.If you keep your case classes at the leafs of any inheritance graphs, you'll be fine.
您将获得定义的任何参数的属性,并且它们将是 val(即,finals)。
您也可以通过常规(即非 case 类)获得此行为:
Case 类还带来了许多其他东西,例如equal、hashcode 和 toString 的有用实现以及带有工厂方法的伴随对象,消除了使用 new 的需要。
正如您所看到的,案例类不需要实现您想要的目标,但它可以让您快速实现目标。至于副作用,定义案例类会在幕后生成一些代码,以提供上一段中描述的内容。这些通常很有用,我往往不会担心它们,但了解它们还是有好处的。
You will get properites for any parameters defined and they will be vals (i.e., finals)
You can get this behavior with regular (i.e., non-case classes) as well:
Case classes also bring a lot of other things as well such as a useful implementations of equality, hashcode and toString and a companion object with a factory method that eliminates the need to use new among other things.
As you can see, a case class is not required to achieve what you want but it gets you there quickly. As for side effects, defining a case class generates some bit of code behind the scenes to give you what was described in the previous paragraph. These are often useful and I tend not to worry about them but it is good to know about them.
除了已经提到的几点之外,案例类在概念上与 Java 中所谓的“值类”很接近。当然,没有什么可以阻止您编写可变的案例类或具有大量功能但数据很少的案例类,但这可能会让使用您的代码的其他人感到惊讶。根据经验,我想说在创建案例类之前至少要三思而行……
Additional to the already mentioned points, a case class is conceptually close to what you would call a "value class" in Java. Of course nothing stops you from writing mutable case classes or case classes with heavy functionality but few data, but this could surprise others working with your code. As a rule of thumb I'd say at least think twice before creating case classes...
其他答案都很好,但他们错过的一个真正的风险是案例类具有值相等性,其行为与标准面向对象的身份相等性非常不同。两个 case 对象相等,当且仅当它们的所有字段都相等。这正是某些情况下所需要的,但在另一些情况下却非常出乎意料。特别是,向具有相等值的东西添加可变状态是自找麻烦。您很容易发现自己的对象的散列码随时间而变化,从而导致 HashMap 损坏和其他类似的问题。
为了节省一些击键次数而将某些东西声明为案例类,将您的属性声明为“val”是错误的经济做法,并且有一天会咬您。
The other answers are all fine, but the one real risk they miss is that case classes have value equality, which behaves very differently from standard object-oriented identity equality. Two case objects are equal iff all of their fields are equal. This is exactly what is needed in some cases, but very unexpected in others. In particular, adding mutable state to something with value equality is asking for trouble. You could easily find yourself with objects whose hashcode changes with time, resulting in corrupted HashMaps and other such nastiness.
Declaring something a case class in order to save a few keystrokes declaring your properties as "val" is false economy, and will someday bite you.