26

注: この質問は興味本位で行っているものであり、言語機能の重要性について質問しているわけではありません。

プログラミングの命令的な世界の人々に紹介された素晴らしい機能のようです。私は Scala を初めて使用しますが、その大規模な構成セットがどこに収まり、活用できるのかをまだ把握しようとしています。

パターン マッチングは、確実に switch ケースよりも 100 倍優れた処理を実行できます。それでも、OOP が登場して以来、ポリモーフィズムを優先するために使用されてきた大文字と小文字の構造です。

つまり、私が理解するのが難しいと感じているのは、スイッチケースが重複を助長し、ケース関連のコードをそれぞれのクラスに記述するほうがよい場合、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の計算がその定義から分離され、多形のビジターパターンよりもはるかに読みやすくなります。

パターンマッチングは非常に簡単なので、どこでも使用できます。ほとんどのオブジェクト指向言語では考えもしなかった場所で見つけることができます。優れた例は、代数的データ型(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"
    ...
  }
}

これをVisitorパターンで実装して、たくさんの楽しみをお祈りします。

于 2012-07-24T11:10:42.087 に答える
2

パターン マッチングによって OOP が完成し、よりモジュール化されたプログラミングが可能になるポイントはほとんどありません。

  1. 大規模なプロジェクトの場合、ドメイン クラス内に「過剰な動作」を入れないようにする必要があります。動作を外部に移動できます。通常、階層の最上位にあるクラスを受け取り、子クラスと照合するメソッドがあります。

  2. 特定のライブラリを使用していて、動作を追加したいが、ソースを変更できない場合。これには暗黙的な変換を使用することもできますが、単純なケースではパターン マッチングの方が高速で簡単です。

あなたの質問に答えるために、コードの再利用パターン マッチングがもたらす可能性があることを過小評価していると思います: PartialFunctionを作成する match ブロックを作成するとき。パターン マッチング ブロックを再利用する必要がある場合は、 orElse メソッドを通じて PartialFunction チェーンを使用できます。これは、一致が順番に実行されるため、特定のオブジェクトのハンドラの階層セットを設計するときにも利点があります。

于 2012-07-24T11:06:39.110 に答える
1

継承とケース構造はどちらも、ポリモーフィズムを実現するための有効な方法です。それらは、わずかに異なる状況で優れています。継承ベースのポリモーフィズムとは異なり、パターン マッチは拡張可能ではありませんが、多くの場合、その必要はありません。Option、Either、:: などの関数型プログラミングの多くの構造は、ポリモーフィズムと if ステートメントを使用するパターン マッチでより簡潔に使用できます。一般に、どのような問題もどちらのタイプのポリモーフィズムでも解決できます。それはエレガンスの問題です。

于 2012-07-24T10:37:51.160 に答える
1

あなたがそれらを虐待した場合、彼らは実際にその正確な問題を抱えているわけではありません.

継承によるポリモーフィが、実際にはそのクラスに属さないあらゆる種類のメソッドをクラスに引き付けてしまうと、問題が発生するのと同じように。

Java は継承をかなり強力にサポートしていますが、switch ステートメントは単なる冗談です。

Scala では、継承と驚くべきパターン マッチングがさらに強力にサポートされています。

釘に適したハンマーを選ぶのはあなたの仕事です。

于 2012-07-24T11:15:18.470 に答える