26

注意:我问这个问题是出于好奇,而不是质疑语言功能的重要性。

看起来是向命令式编程世界的人们介绍的一个很棒的功能。我是 Scala 的新手,仍然试图找出所有的地方,让它的大量构造适合并且可以被利用。

模式匹配绝对可以比 switch 案例做得好 100 倍。但是,自从 OOP 出现以来,它仍然是一个案例构造,我们习惯于使用多态性。

所以简而言之,我发现难以理解的是,如果 switch case 鼓励重复,我们最好将与 case 相关的代码编写到各自的类中,那么 Scala 的模式匹配如何克服这个问题?

我们仍然可以为各种情况使用类或泛型类,并再次利用多态性来满足我们的需要。

4

5 回答 5

18

这是对象和数据结构之间差异的问题。

如果您正在处理对象,请使用子类型多态性 - 添加新类型不需要重新编译、重新测试或重新部署现有类型,而添加新算法(接口上的方法,位于层次结构的顶部)则需要.

如果您正在处理数据结构,请使用模式匹配 - 添加新算法不需要重新编译、重新测试或重新部署现有算法,而添加新类型则需要。

在此处阅读更多相关信息。

于 2012-07-24T11:10:11.807 回答
4

模式匹配是一个很棒的功能,因为它易于使用。

它比广泛使用的面向对象语言中的大多数设计模式解决了“如何为对象系统带来功能”的问题。例如有访问者模式,它将算法与其对象结构分开。这个想法很棒,因为它允许我们改变对象的行为而无需触及它们的类。但另一方面,这种模式在符号的过于复杂和冗长方面失败了。使用模式匹配,这可以很容易地解决:

def calc(e: Expression): Double = e match {
  case Num(n) => n
  case Add(a, b) => calc(a)+calc(b)
  case Sub(a, b) => calc(a)-calc(b)
  ...
}

这将 AST 的计算与其定义分开,并且比多态访问者模式更易于阅读。

因为模式匹配非常简单,所以我们可以在任何地方使用它——你会在大多数 OO 语言中从未想过的地方找到它。一个很好的例子是 Actors,它使用代数数据类型 (ADT) 在彼此之间进行通信:

sealed trait Message
case class Hello(name: String) extends Message
case class Bye(name: String) extends Message
case class Question(q: Symbol) extends Message

class MySelf extends Actor {
  def receive {
    case Hello(name) => println("Hello "+name)
    case Bye(name) => println("Buy "+name)
    case Question('AreYouOk) => sender answer "I'm ok"
    ...
  }
}

我希望通过使用访问者模式来实现这一点,你会获得很多乐趣!

于 2012-07-24T11:10:42.087 回答
2

我看到很少有模式匹配完成 OOP 并允许更多模块化编程的地方。

  1. 当您有一个大项目时,您希望避免在您的域类中放置“过多的行为”。您可以将行为移到外部,并且通常有一个方法在层次结构的顶部接收一个类并与子类匹配。

  2. 当您使用特定库并且想要添加行为但无法修改源时。您也可以为此使用隐式转换,但在简单的情况下,模式匹配更快更容易。

要回答您的问题,我可能会说您低估了模式匹配可以带来的代码重用:当您创建一个创建PartialFunction的匹配块时。如果需要重用模式匹配块,可以通过 orElse 方法使用 PartialFunction 链接。这在设计特定对象的分层处理程序集时也带来了好处,因为匹配是按顺序执行的。

于 2012-07-24T11:06:39.110 回答
1

继承和案例构造都是实现多态性的有效方法。它们在稍微不同的情况下都很好。与基于继承的多态性不同,模式匹配是不可扩展的,但您通常不需要它。函数式编程中的许多结构,例如 Option、Either 或 :: 可以更简洁地与 oop 多态性和 if 语句的模式匹配一​​起使用。一般来说,任何问题都可以用任何一种多态性来解决。这只是优雅的问题。

于 2012-07-24T10:37:51.160 回答
1

如果您滥用它们,它们实际上并没有确切的问题。

正如继承的多态性会导致您的类吸引不属于该类的各种方法时遇到问题一样。

虽然 Java 对继承有一些合理的强大支持,但 switch 语句只是一个笑话。

在 Scala 中,您对继承和惊人的模式匹配有更强大的支持。

为你的钉子挑选合适的锤子是你的工作。

于 2012-07-24T11:15:18.470 回答