Clojureのマルチメソッドを理解しようと、しばらく時間を費やしました。私が理解している限り、主な「プロ」マルチメソッドの議論はその柔軟性ですが、マルチメソッドが単純なifまたはcaseステートメントよりも優れている理由の議論と混同しています。誰か、ポリモーフィズムと誇張されたcaseステートメントの境界線はどこにあるのか説明してもらえますか?
編集:「if」ステートメントと比較してもっと興味があるという質問をもっと明確にすべきでした。答えてくれてありがとう!
Clojureのマルチメソッドを理解しようと、しばらく時間を費やしました。私が理解している限り、主な「プロ」マルチメソッドの議論はその柔軟性ですが、マルチメソッドが単純なifまたはcaseステートメントよりも優れている理由の議論と混同しています。誰か、ポリモーフィズムと誇張されたcaseステートメントの境界線はどこにあるのか説明してもらえますか?
編集:「if」ステートメントと比較してもっと興味があるという質問をもっと明確にすべきでした。答えてくれてありがとう!
タイプA、B、C、D、およびEがあり、メソッドm1、m2、m3が前のタイプの単一の引数を取るとします。次のようなテーブルに配置できます。
| A | B | C | D | E |
m1 | | | | | |
m2 | | | | | |
m3 | | | | | |
「switch」ステートメント戦略は、一度にこのテーブルの1行を実装します。新しいタイプFを追加するとします。それをサポートするには、すべての実装を変更する必要があります。
クラスベースのポリモーフィズム(C ++、Javaなど)を使用すると、代わりに列全体を実装できます。したがって、すでに定義されているクラスを変更する必要がないため、新しいタイプを追加するのは簡単です。ただし、他のすべてのタイプに追加する必要があるため、新しいメソッドを追加するのは困難です。
マルチメソッドを使用すると、テーブルの単一のセルを互いに独立して実装できます。
複数の引数をディスパッチする必要がある場合、この柔軟性はさらに大きくなります。新しい引数ごとにこのテーブルに別の次元が追加され、スイッチベースとクラスベースの両方のディスパッチが非常に迅速に複雑になります(Visitorパターンを参照)。
マルチメソッドは、引数のタイプだけでなく、ほとんどすべてのものにディスパッチできるため、実際には示されているよりもさらに一般的であることに注意してください。
マルチメソッドと大きなifステートメントの違いは、ケースステートメントを含む関数を変更して、ケースをifステートメントに追加する必要があることです。既存のメソッドに触れることなく、新しいメソッドを追加できます。
したがって、ライブラリ内でマルチメソッドを定義し、ユーザーがそれを独自のデータ型に拡張できるようにしたい場合は、問題ありません。代わりにifステートメントを使用した場合、それは大きな問題になります。
上記のivantの答えは、この記事を参照することで拡張できます。それはプロトコルの力を説明するのに良い仕事をします。マルチメソッドは、多くの次元を持つプロトコルと考えてください。