Scala的模式匹配是否违反了开放/封闭原则?

时间:2009-02-18 23:41:22

标签: oop scala pattern-matching design-principles

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

临: Odersky1Odersky2

缺点: Beust

每种情况下的评论都非常好。模式匹配是令人兴奋的东西还是我应该避免使用的东西?实际上,我认为答案是“它取决于你何时使用它”,但它有哪些积极的用例以及哪些是消极的?

3 个答案:

答案 0 :(得分:22)

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

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

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

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

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

答案 1 :(得分:16)

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

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

因此,奥德斯基博士的观点将是值得信赖的人,特别是考虑到他在面向对象编程和设计领域所做的大量研究。

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

答案 2 :(得分:1)

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

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

相关问题