如果您正在编写使用大量漂亮的、不可变的数据结构的代码,case类似乎是天赐之物,只需一个关键字就可以免费获得以下所有内容:
但是将不可变的数据结构定义为case类有哪些缺点呢?
它对类或其客户端设置了哪些限制?
在某些情况下,您应该选择非案例类吗?
发布于 2011-01-11 02:02:56
一个很大的缺点是:案例类不能扩展一个案例类。这就是限制。
您忽略的其他优点,列出了完整性:兼容序列化/反序列化,不需要使用“新”关键字来创建。
对于具有可变状态、私有状态或无状态(例如,大多数单例组件)的对象,我更喜欢非大小写类。几乎所有其他东西的案例类。
发布于 2011-01-11 10:37:42
首先是好的部分:
默认情况下,所有不可变的
是的,如果需要,甚至可以重写(使用var__)。
Getters自动定义
在任何类中都可以通过用val前缀params来实现
像样的
是的,非常有用,但如果需要的话,可以在任何类上使用。
兼容的和
结合简单的模式匹配,这是人们使用用例类的主要原因。
用unapply() 方法匹配的伴随对象
也可以使用提取器手工处理任何类。
此列表还应包括uber-功能强大的复制方法,这是Scala 2.8中最好的方法之一。
那么不好的是,只有少数几个真正的限制与案例类:
不能使用与编译器生成的方法相同的签名在同伴对象中定义apply。
但在实践中,这很少是一个问题。所生成的应用方法的变化行为保证会给用户带来惊喜,并且应该极力阻止,这样做的唯一理由是验证输入参数--这是在主构造器主体中最好完成的一项任务(在使用copy时也使验证可用)。
你不能子类
是的,尽管case类本身仍然有可能成为后代。一个常见的模式是建立一个特征的类层次结构,使用case类作为树的叶节点。
同样值得注意的是sealed修饰符。带有此修饰符的特征的任何子类都必须在同一个文件中声明。当模式与特征的实例进行匹配时,如果没有检查所有可能的具体子类,编译器就可以警告您。当与case类结合时,如果代码在没有警告的情况下编译,则可以提供非常高的信任级别。
作为Product类的子类,case类不能有超过22个参数
没有真正的解决办法,除了停止使用这许多params的类:)
还有..。
有时还会注意到的另一个限制是Scala (目前)不支持惰性参数(比如lazy val,而是作为参数)。解决这一问题的方法是使用名为param,并将其分配给构造函数中的惰性val。不幸的是,按名字命名的参数不能与模式匹配混合,这将防止这种技术在破坏编译器生成的提取器时与case类一起使用。
如果您想要实现高功能的惰性数据结构,这是相关的,并且希望通过在Scala的未来版本中添加惰性params来解决。
发布于 2011-01-11 21:55:29
我认为TDD原则适用于此:不要过度设计.当您声明某物为case class时,您将声明许多功能。这将减少将来更改类的灵活性。
例如,case class在构造函数参数上有一个equals方法。当您第一次编写类时,您可能并不关心这一点,但后者可能会决定您希望相等性忽略其中一些参数,或者做一些稍微不同的事情。但是,客户端代码可以在依赖于case class相等的同时编写。
https://stackoverflow.com/questions/4653424
复制相似问题