3

複数のディスパッチの概念(つまり、仮想メソッドの動的ディスパッチがメソッドの引数にも拡張されているかのような組み込みサポート) をオブジェクト指向言語に含める必要があるかどうか疑問に思います。無視できる。

問題

次のシナリオを考えてみましょう: 動物の種類を含む (必ずしも平坦ではない) クラス階層があります。コード内のさまざまな場所で、動物オブジェクトに対していくつかのアクションを実行したいと考えています。このオブジェクト参照がどのように取得されるかは気にしませんし、制御することもできません。動物のリストをトラバースすることで遭遇するかもしれませんし、メソッドの引数の 1 つとして与えられるかもしれません。実行したいアクションは、特定の動物のランタイム タイプに応じて特化する必要があります。そのようなアクションの例は次のとおりです。

  • GUI で表示するために、動物のビュー モデルを構築します。
  • このタイプの動物を表すデータ オブジェクトを作成します (後で DB に格納します)。
  • 動物にエサを与えますが、動物の種類に応じて異なる種類のエサを与えます (動物にとってより健康的なもの)。

これらの例はすべて動物オブジェクトのパブリック API で動作しますが、それらが行うことは動物自身のビジネスではないため、動物自体に組み込むことはできません。

ソリューション

1 つの「解決策」は、型チェックを実行することです。しかし、このアプローチはエラーが発生しやすく、リフレクション機能を使用します。これは (私の意見では) ほとんどの場合、設計が悪いことを示しています。型はコンパイル時の概念のみであるべきです。

もう 1 つの解決策は、ビジター パターンを「悪用」(一種) して、二重ディスパッチを模倣することです。しかし、これには、訪問者を受け入れるように動物を変更する必要があります。

他のアプローチがあると確信しています。また、拡張の問題にも対処する必要があります。新しいタイプの動物がパーティーに参加した場合、いくつのコード位置を適応させる必要があり、どうすればそれらを確実に見つけることができますか?

質問

では、これらの要件に照らして、適切に設計されたオブジェクト指向言語に複数ディスパッチを組み込むべきではないでしょうか?
特定のオブジェクトの動的タイプに依存する外部 (内部だけでなく) アクションを作成するのは自然なことではありませんか?

よろしくお願いします!

4

3 に答える 3

0

型 X のオブジェクトが型 Y のオブジェクトをどのように変換するかについての知識が、クラス X またはクラス Y のいずれかに格納されなければならないという状況に自分自身を制限する場合、Y の基本型に、の参照を受け入れるメソッドを含めることができます。 X の基本型であり、その参照によって識別されるオブジェクトによってどのように fnorble されるかについて、オブジェクトがどの程度知っているかを示しYますX

それができたら、特定のタイプの によって fnorble されていることについてどれだけ知っているかを に尋ねることから、XFnorble(Y)メソッドを開始することができます。がについて知っている以上に知っている場合、のメソッドは Y のメソッドを呼び出す必要があります。それ以外の場合は、最善の方法でfnorble する必要があります。YXYXXYXFnorble(Y)BeFnorbledBy(X)XY

の種類がいくつあるかに応じて、さまざまな種類の のXオーバーロード メソッドを定義できます。これにより、呼び出し時に適切なメソッドに自動的に直接ディスパッチされます。ただし、そのようなアプローチでは、特定のタイプ自体に興味があるかどうかに関係なく、誰にとっても「興味深い」すべてのタイプについてすべての人が知る必要があります。YYBeFnorbledByXXtarget.BeFnorbledBy(this)YX

このアプローチは、X も Y も直接認識していない X が Y をどのように変換するかについて知っているクラス Z の外部オブジェクトが存在する可能性がある状況に対応していないことに注意してください。この種の状況は、さまざまな種類の X がさまざまな種類の Y をどのように解釈するかを知っているすべてのものがルールブックに伝えることができる「ルールブック」オブジェクトを持つことによって最もよく処理され、X が Y を解釈することを望むコードはルールブックに要求できます。それを実現します。ルールブックがシングルトンの場合は言語が役立ちますが、複数のルールブックがあると便利な場合もあります。そのような場合のセマンティクスは、コードでルールブックを直接使用することによっておそらく最もよく処理されます。

于 2015-05-26T18:48:30.427 に答える
0

実行時の実際の引数の型と組み合わせたメソッド名/シグネチャに基づく動的ディスパッチを提案しています。私はあなたが狂っていると思います。

では、これらの要件に照らして、複数のディスパッチは適切に設計されたオブジェクト指向言語の不可欠な部分であるべきではないでしょうか?

あなたが想像している種類のディスパッチ戦略が利用可能であるとコーディングが簡素化されるという問題があるということは、そのようなディスパッチが特定の言語に組み込まれていることに対する弱い議論です。

特定のオブジェクトの動的タイプに依存する外部 (内部だけでなく) アクションを作成するのは自然なことではありませんか?

おそらく、「自然」に見えるすべてが実際には良い考えであるとは限りません。たとえば、衣服は自然ではありませんが、衣服を着用せずに公共の場を歩き回るとどうなるか見てみましょう (いずれにせよ、バークレー以外の場所)。

一部の言語には、引数の型に基づいた静的ディスパッチが既にあり、より慣例的に「オーバーロード」と呼ばれています。一方、引数の型に基づく動的ディスパッチは、考慮すべき引数が複数ある場合は本当に混乱し、遅くなるしかありません。今日の一般的な OO 言語では、必要な場所でダブル ディスパッチを実行できますが、必要のない場所の大部分でそれをサポートするというオーバーヘッドはありません。

さらに、二重ディスパッチを実装すると、個別のコンポーネント間の密結合から生じるメンテナンスの問題が発生しますが、それを管理しやすくするのに役立つコーディング戦略があります。とにかく、特定の言語に組み込まれた引数ベースの複数のディスパッチが実際にその問題にどの程度役立つかは不明です。

于 2015-05-26T18:46:36.577 に答える