14

如果我添加一个新的案例类,这是否意味着我需要搜索所有模式匹配代码并找出需要处理新类的位置?我最近一直在学习这门语言,当我读到一些支持和反对模式匹配的论点时,我一直对应该在哪里使用它感到困惑。请参阅以下内容:

专业版: Odersky1Odersky2

缺点: 比斯特

每种情况下的评论也都很好。那么模式匹配是令人兴奋的东西还是我应该避免使用的东西?实际上,我想答案是“这取决于您何时使用它”,但是它有哪些积极的用例,哪些是消极的用例?

4

3 回答 3

22

杰夫,我认为你有正确的直觉:这取决于。

当您有一组相对固定的方法需要实现时,具有虚拟方法分派的面向对象的类层次结构很好,但是许多潜在的子类可能从层次结构的根继承并实现这些方法。在这样的设置中,添加新子类相对容易(只需实现所有方法),但添加新方法相对困难(您必须修改所有子类以确保它们正确实现新方法)。

当您拥有一组相对固定的属于某个数据类型的类时,具有基于模式匹配功能的数据类型是很好的,但有许多潜在的函数对该数据类型进行操作。在这样的设置中,为数据类型添加新功能相对容易(只需对其所有类进行模式匹配),但添加作为数据类型一部分的新类相对困难(您必须修改所有匹配的函数数据类型以确保它们正确支持新类)。

OO 方法的典型示例是 GUI 编程。GUI 元素需要支持非常少的功能(在屏幕上绘制自己是最低限度的),但新的 GUI 元素一直在添加(按钮、表格、图表、滑块等)。模式匹配方法的典型示例是编译器。编程语言通常具有相对固定的语法,因此语法树的元素很少更改(如果有的话),但不断添加对语法树的新操作(更快的优化,更彻底的类型分析等)。

幸运的是,Scala 允许您将这两种方法结合起来。案例类既可以进行模式匹配,也可以支持虚拟方法分派。常规类支持虚拟方法分派,并且可以通过在相应的伴随对象中定义提取器来进行模式匹配。由程序员决定何时每种方法都合适,但我认为这两种方法都是有用的。

于 2009-02-19T09:17:52.110 回答
16

虽然我尊重塞德里克,但他在这个问题上完全错了。Scala 的模式匹配可以在需要时从类更改中完全封装。虽然对案例类的更改确实需要更改任何相应的模式匹配实例,但这只是在以幼稚的方式使用此类类时。

Scala 的模式匹配总是委托给类的伴随对象的解构器。使用案例类,这个解构器是自动生成的(连同伴随对象中的工厂方法),尽管仍然可以覆盖这个自动生成的版本。在任何时候,您都可以断言对模式匹配过程的完全控制,从而将任何模式与类本身的潜在变化隔离开来。因此,模式匹配只是通过封装的安全过滤器访问类数据的另一种方式,就像任何其他方法一样。

因此,Odersky 博士的观点在这里值得信赖,特别是考虑到他在面向对象编程和设计领域进行的大量研究。

至于用在什么地方,完全看个人口味。如果它使您的代码更简洁和可维护,请使用它!否则,不要。对于大多数面向对象的程序,模式匹配是不必要的。但是,一旦您开始集成更多功能性惯用语(OptionList等),我想您会发现模式匹配将显着减少句法开销并提高类型系统提供的安全性。一般来说,任何时候你想提取数据同时测试一些条件(例如从 中提取一个值Some),模式匹配可能会很有用。

于 2009-02-19T03:01:36.693 回答
1

如果你在做函数式编程,模式匹配绝对是好的。在 OO 的情况下,在某些情况下它是好的。在 Cedric 的示例本身中,这取决于您从概念上如何看待该print()方法。它是每个Term对象的行为吗?还是它之外的东西?我会说它在外面,并且进行模式匹配是有意义的。另一方面,如果您有一个Employee具有各种子类的类,那么在基类中对它的属性(比如名称)进行模式匹配是一个糟糕的设计选择。

模式匹配也提供了一种解包类成员的优雅方式。

于 2009-02-19T07:08:38.533 回答