問題タブ [double-dispatch]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票する
1 に答える
2360 参照

c++ - 複数の訪問可能なパラメーターを持つC++の訪問者パターン

次の階層について考えてみます。

およびビジタークラス:

通常、オーバーロードメソッドがパラメータータイプに依存する場合、ビジターパターンを使用してダブルディスパッチを実現しますが、基本クラスへのポインターしかありません。

例えば:

仮想関数の動的バインディングは、メソッドが呼び出されたオブジェクトでのみ発生し、そのパラメーター(派生型)では発生しないため、これがダブルディスパッチを実現する唯一の方法だと思います。

今、私は新しい状況に遭遇しました。そこでは、複数のパラメーターでオーバーロードする一種のVisitメソッドが必要です。このようなもの:

acceptメソッドはパラメーターの1つでのみ呼び出されるため、従来のビジターパターンソリューションを使用できません。

私の質問は、この状況で使用できる同様のビジターパターンソリューションまたは同様のものが存在するかどうかです。(Visitを正確に2つのパラメーター、2つ以下でオーバーロードする必要があります)。

0 投票する
3 に答える
16206 参照

c++ - 二重ディスパッチ C++ を理解する

ダブルディスパッチがどのように機能するかを理解しようとしています。抽象クラス Creature から派生したモンスターと戦士が戦う例を作成しました。クラスCreatureには、派生クラスで定義されたメソッド「fight」があり、各派生クラスでは、戦士が戦士またはモンスターなどと戦う場合に何が起こるかが定義されています。私は次のコードを書きました:

これにより、コンパイラ エラーが発生します。

ex12_10.cpp: メンバー関数 'virtual void Monster::fight(Creature&)': ex12_10.cpp:17:30: エラー: 'class Creature' には 'fightwho' という名前のメンバーがありません

ex12_10.cpp: メンバー関数 'virtual void Warrior::fight(Creature&)': ex12_10.cpp:24:29: エラー: 'class Creature' には 'fightwho' という名前のメンバーがありません</p>

しかし、ここから先の進め方がわかりません... 助けてください。

0 投票する
3 に答える
410 参照

c++ - ジオメトリ ライブラリ内のアルゴリズムとデータの分離 (トリプル ディスパッチが必要ですか?)

アプリケーションのジオメトリを扱う部分の設計に問題があります。特に、クラスの階層と交差のための個別のメソッドが必要です。

問題

階層は次のようになります。

  • ジオメトリ
    • メッシュ
    • パラメトリック
      • 球体

そして、交差メソッドは次のようになります。

これは非常に簡単です。std::vector問題が発生するのは、すべてのジオメトリを 1 つの構造(または KD ツリーなど) にまとめて格納したい場合です。

そのためには、を使用する必要がありますstd::vector<Geometry*>。ただし、このベクトルから読み取るとGeometry*オブジェクトが取得されるため、適切な交差関数を呼び出す方法がありません。

問題の例:

ジオメトリ オブジェクト内にアルゴリズムを実装した場合、問題はビジターと非常に奇妙な関数呼び出しのバウンスによって解決される可能性があります。

ただし、交差アルゴリズムは Geometry クラスの外に置きたいと思います。理由は次のとおりです。

  • どちらが所有権を持つべきかの決定を避けるため (例えば、ボックスと球の間の交差をどこに実装しますBoxSphere?)

  • ジオメトリ オブジェクトが乱雑になるのを避けるために、ジオメトリに対してできることはすべてです。これは非常に多くのことです (ほんの数例を挙げると、ボクセル化、交点の計算、建設的なジオメトリ オペレータの適用など)。したがって、ロジックをデータから分離することは、ここでは非常に望ましいことです。

一方、特定のジオメトリを抽象化できるものがあるため、テンプレートの代わりに階層が必要です... (たとえば、std::vector、または KD ツリー、または... に格納するため)。

これをどのように解決しますか?これに適したデザインパターンはありますか?私はいくつかのライブラリを見てみましたが、私はすでにそうであったことにもっと混乱しました...

最も簡単な方法 (時々使用される) は、RTTI (またはそれを偽造する) とダウンキャストを使用することですが、それは正確には維持できません... (新しいジオメトリを追加すると、すべてのコードで多くの switch ステートメントを変更する必要があります)。

何かご意見は?

よろしくお願いします。

0 投票する
2 に答える
5321 参照

java - Java の例での二重ディスパッチ

DDに関するウィキペディアの記事を読んでいて、最後にある「Java でのダブル ディスパッチと例」リンクにジャンプしました。次の Serializable の例の説明は、私にとってかなり混乱しているようです。

説明は次のとおりです。

A をシリアル化するために、ObjectOutputStreamまずメソッドwriteObject( ObjectOutputStream oos)が存在するかどうかを確認します。存在する場合は、それ自体を引数としてそのメソッドを呼び出します。次に、writeObjectメソッドは呼び出しを にディスパッチしますObjectOutputStream(したがって、これは二重ディスパッチになります)。この非常に単純なコールバックを行う際に、ObjectOutputStreamは次のように述べています。「このストリームに状態を​​書き込む責任をあなたに委任します」その単純な選択を行うことで、ObjectOutputStreamはオブジェクトから切り離されましAた。オブジェクトAは、OK を返します。ここに、ストリームに書き込みたい状態があります。値がプリミティブの場合、write メソッドのオーバーロードによって処理できます。そうでない場合は、すべての有用な状態がストリームに配置されるまで、オブジェクト グラフの次のレベルで前後に続行できます。

説明されているのは舞台裏で起こっていることであり、提示されたコードではないため、説明が混乱している可能性があると思います。ここに私を混乱させる部分があります:

  • ObjectOutputStreamまず、メソッドwriteObject( ObjectOutputStream oos)が存在するかどうかを確認します」。ObjectOutputStreamこのメソッドは独自のメソッドであるため、このメソッドの存在を確認する必要があるのはなぜですか?
  • 「そうであれば、それ自体を引数としてそのメソッドを呼び出します」。writeObjectのインスタンスをA引数として呼び出しているように見えます。前の項目に戻ると、 のインスタンスで呼び出されているのに、なぜ argでwriteObject署名を探すのでしょうか?ObjectOutputStreamA
  • writeObjectその後、メソッドは呼び出しをにディスパッチしますObjectOutputStream(したがって、これを二重ディスパッチにします)」。繰り返しますが、writeObjectメソッドはクラスに属しているため、元の宛先のように見えるためObjectOutputStream、これがどのように「にディスパッチされているか」を確認できません。ObjectOutputStream

ここで基本的な何かが欠けているだけですか、それともこれは不十分に書かれた/説明された例ですか? それが悪い例である場合は、ウィキペディアの記事をより良い例に変更したいので、お気軽に提案をお寄せください.

ありがとう。

0 投票する
1 に答える
1131 参照

python - モデルからビュー情報を抽出するための最も Pythonic な二重ディスパッチ

PySide を使用して、Python と Qt でデスクトップ アプリをコーディングしています。トップレベルのアイテムがその子とは異なるタイプのオブジェクトであるツリー ビューを表示する必要があります。具体的には、最上位アイテムは Git リポジトリであり、その子は作業ツリー内のディレクトリです。

リポジトリの場合、そのパスと現在チェックアウトされているブランチを表示したいと考えています。ディレクトリの場合、その名前を表示したいだけです。

現時点では、下位のモデル オブジェクト (メソッドから取得) をQAbstractItemModel子孫に使用させ、結果の文字列をフォーマットする方法を決定することでこれを行います。isinstanceinternalPointer()

この種の二重ディスパッチを行うための、より Pythonic な (またはより不格好な) 方法があるかどうか疑問に思っていました。

私がやりたくないのは、Git リポジトリと作業ツリー ファイルのモデル クラスでこの目的のためのメソッドを定義することです。これは SRP に違反すると思うからです。

どんな考えやアイデアでも大歓迎です。また、誰かがこの質問のより不格好なタイトルを考えられる場合は、私に知らせてください ;)

0 投票する
2 に答える
519 参照

java - Java での二重ディスパッチの自動化

私は2つのインターフェースを持っていますQueryFilter単純Query化のための例のクラスです。今のところ1つのクエリがあります)、実際のフィルターに応じて関数を書きたいと思います。Query.applyFilter()つまりNameFilter、および他DateFilterすべてのフィルターの異なる関数です。

私の解決策は次のとおりです。

それでは、ここmodifyQuery()ですべての Filter クラスの実装を書き直す必要があります。

次に、C ++でそれを回避する方法があります:テンプレートを使用してキャストしmodifyQuery()ます:

デモ

しかし、ジェネリックはテンプレートと同じように動作しないため、Java でこのソリューションを使用することはできません。コピーと貼り付けを避けるために Java で使用できるものは何ですか?

0 投票する
2 に答える
233 参照

java - Java での二重ディスパッチ

二重発送について間違った考えを持っているかどうかはわかりません。しかし、これは私が考えたことです:

Javas Single diapatch により、Java は実行時に objA を Achild に正しく解決し、パラメーターはコンパイル時に B に解決されると思いました。どこを間違えたのか教えてください。

0 投票する
1 に答える
179 参照

c++ - C++ 互いに相対的ではないオブジェクトを使用して Double ディスパッチ メソッドを呼び出す

互いに交差しているかどうかを確認できる一連の形状オブジェクトがあります (いずれかのオブジェクトの一部が他のオブジェクトと重なっている場合、交差は true です)。これは、2 つのオブジェクトの交差をいずれかのオブジェクトに対して相対的に表すことができ、依然として有効かつ真であるため、二重ディスパッチでうまく機能します。

最近、図形が別の図形を完全に囲んでいるかどうかをテストする Contains メソッドを追加しました (「追加しようとしました」と読みます)。サイズの異なる 2 つの形状は Intersect では機能しますが、Contains では機能しないため、二重ディスパッチは失敗します。shape_oneは大きな円であり、 でshape_two完全に囲まれた小さな円shape_oneです。呼び出しshape_one.Contains(shape_two)は true を返しますが、shape_two.Contains(shape_one)false を返します。

このタイプのシナリオで二重ディスパッチを実装する方法はありますか?

(質問の理解を深めるために、タイトルの編集をお勧めします...)

二重ディスパッチを使用した Intersects メソッドのサンプル:

二重ディスパッチを含む Contains メソッドのサンプル:

0 投票する
2 に答える
725 参照

c# - 関数とオブジェクトの両方を操作するための拡張可能な C# での二重ディスパッチの実装

メソッドとクラスの両方に拡張できる二重ディスパッチを実装する方法を探しています。

これまでは、基本的に次の 3 つのアプローチを使用していました。

  • 優れた従来の手続き型アプローチswitch(新しい関数を追加するのは簡単で、新しいクラスを追加するのは難しい)
  • 訪問者パターン (非常に似ています: 新しい訪問者を追加するのは簡単ですが、新しいクラスを追加するのは難しいです)
  • シンプルなインターフェイス アプローチ (新しいクラスを追加するのは簡単ですが、新しい関数を追加するのは難しい)

関数や既存のクラスを変更せずに、新しい関数と新しいクラスの両方を追加できる方法を探しています。

これは、オブジェクト/関数の特定の組み合わせを要求しても失敗しないはずです。少なくとも、プログラムの起動後に一度実行できるチェックの後ではありません。

これまでに使用したアプローチは次のとおりです。

従来の手続き型アプローチ:

従来のオブジェクト指向アプローチ (ビジター パターン):

シンプルなインターフェースアプローチ: