問題タブ [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.
c++ - 複数の訪問可能なパラメーターを持つC++の訪問者パターン
次の階層について考えてみます。
およびビジタークラス:
通常、オーバーロードメソッドがパラメータータイプに依存する場合、ビジターパターンを使用してダブルディスパッチを実現しますが、基本クラスへのポインターしかありません。
例えば:
仮想関数の動的バインディングは、メソッドが呼び出されたオブジェクトでのみ発生し、そのパラメーター(派生型)では発生しないため、これがダブルディスパッチを実現する唯一の方法だと思います。
今、私は新しい状況に遭遇しました。そこでは、複数のパラメーターでオーバーロードする一種のVisitメソッドが必要です。このようなもの:
acceptメソッドはパラメーターの1つでのみ呼び出されるため、従来のビジターパターンソリューションを使用できません。
私の質問は、この状況で使用できる同様のビジターパターンソリューションまたは同様のものが存在するかどうかです。(Visitを正確に2つのパラメーター、2つ以下でオーバーロードする必要があります)。
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>
しかし、ここから先の進め方がわかりません... 助けてください。
c++ - ジオメトリ ライブラリ内のアルゴリズムとデータの分離 (トリプル ディスパッチが必要ですか?)
アプリケーションのジオメトリを扱う部分の設計に問題があります。特に、クラスの階層と交差のための個別のメソッドが必要です。
問題
階層は次のようになります。
- ジオメトリ
- メッシュ
- パラメトリック
- 箱
- 球体
そして、交差メソッドは次のようになります。
これは非常に簡単です。std::vector
問題が発生するのは、すべてのジオメトリを 1 つの構造(または KD ツリーなど) にまとめて格納したい場合です。
そのためには、を使用する必要がありますstd::vector<Geometry*>
。ただし、このベクトルから読み取るとGeometry*
オブジェクトが取得されるため、適切な交差関数を呼び出す方法がありません。
問題の例:
ジオメトリ オブジェクト内にアルゴリズムを実装した場合、問題はビジターと非常に奇妙な関数呼び出しのバウンスによって解決される可能性があります。
ただし、交差アルゴリズムは Geometry クラスの外に置きたいと思います。理由は次のとおりです。
どちらが所有権を持つべきかの決定を避けるため (例えば、ボックスと球の間の交差をどこに実装します
Box
かSphere
?)ジオメトリ オブジェクトが乱雑になるのを避けるために、ジオメトリに対してできることはすべてです。これは非常に多くのことです (ほんの数例を挙げると、ボクセル化、交点の計算、建設的なジオメトリ オペレータの適用など)。したがって、ロジックをデータから分離することは、ここでは非常に望ましいことです。
一方、特定のジオメトリを抽象化できるものがあるため、テンプレートの代わりに階層が必要です... (たとえば、std::vector
、または KD ツリー、または... に格納するため)。
これをどのように解決しますか?これに適したデザインパターンはありますか?私はいくつかのライブラリを見てみましたが、私はすでにそうであったことにもっと混乱しました...
最も簡単な方法 (時々使用される) は、RTTI (またはそれを偽造する) とダウンキャストを使用することですが、それは正確には維持できません... (新しいジオメトリを追加すると、すべてのコードで多くの switch ステートメントを変更する必要があります)。
何かご意見は?
よろしくお願いします。
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
署名を探すのでしょうか?ObjectOutputStream
A
- 「
writeObject
その後、メソッドは呼び出しをにディスパッチしますObjectOutputStream
(したがって、これを二重ディスパッチにします)」。繰り返しますが、writeObject
メソッドはクラスに属しているため、元の宛先のように見えるためObjectOutputStream
、これがどのように「にディスパッチされているか」を確認できません。ObjectOutputStream
ここで基本的な何かが欠けているだけですか、それともこれは不十分に書かれた/説明された例ですか? それが悪い例である場合は、ウィキペディアの記事をより良い例に変更したいので、お気軽に提案をお寄せください.
ありがとう。
python - モデルからビュー情報を抽出するための最も Pythonic な二重ディスパッチ
PySide を使用して、Python と Qt でデスクトップ アプリをコーディングしています。トップレベルのアイテムがその子とは異なるタイプのオブジェクトであるツリー ビューを表示する必要があります。具体的には、最上位アイテムは Git リポジトリであり、その子は作業ツリー内のディレクトリです。
リポジトリの場合、そのパスと現在チェックアウトされているブランチを表示したいと考えています。ディレクトリの場合、その名前を表示したいだけです。
現時点では、下位のモデル オブジェクト (メソッドから取得) をQAbstractItemModel
子孫に使用させ、結果の文字列をフォーマットする方法を決定することでこれを行います。isinstance
internalPointer()
この種の二重ディスパッチを行うための、より Pythonic な (またはより不格好な) 方法があるかどうか疑問に思っていました。
私がやりたくないのは、Git リポジトリと作業ツリー ファイルのモデル クラスでこの目的のためのメソッドを定義することです。これは SRP に違反すると思うからです。
どんな考えやアイデアでも大歓迎です。また、誰かがこの質問のより不格好なタイトルを考えられる場合は、私に知らせてください ;)
java - Java での二重ディスパッチの自動化
私は2つのインターフェースを持っていますQuery
(Filter
単純Query
化のための例のクラスです。今のところ1つのクエリがあります)、実際のフィルターに応じて関数を書きたいと思います。Query.applyFilter()
つまりNameFilter
、および他DateFilter
のすべてのフィルターの異なる関数です。
私の解決策は次のとおりです。
それでは、ここmodifyQuery()
ですべての Filter クラスの実装を書き直す必要があります。
次に、C ++でそれを回避する方法があります:テンプレートを使用してキャストしmodifyQuery()
ます:
しかし、ジェネリックはテンプレートと同じように動作しないため、Java でこのソリューションを使用することはできません。コピーと貼り付けを避けるために Java で使用できるものは何ですか?
java - Java での二重ディスパッチ
二重発送について間違った考えを持っているかどうかはわかりません。しかし、これは私が考えたことです:
Javas Single diapatch により、Java は実行時に objA を Achild に正しく解決し、パラメーターはコンパイル時に B に解決されると思いました。どこを間違えたのか教えてください。
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 メソッドのサンプル:
c# - 関数とオブジェクトの両方を操作するための拡張可能な C# での二重ディスパッチの実装
メソッドとクラスの両方に拡張できる二重ディスパッチを実装する方法を探しています。
これまでは、基本的に次の 3 つのアプローチを使用していました。
- 優れた従来の手続き型アプローチ
switch
(新しい関数を追加するのは簡単で、新しいクラスを追加するのは難しい) - 訪問者パターン (非常に似ています: 新しい訪問者を追加するのは簡単ですが、新しいクラスを追加するのは難しいです)
- シンプルなインターフェイス アプローチ (新しいクラスを追加するのは簡単ですが、新しい関数を追加するのは難しい)
関数や既存のクラスを変更せずに、新しい関数と新しいクラスの両方を追加できる方法を探しています。
これは、オブジェクト/関数の特定の組み合わせを要求しても失敗しないはずです。少なくとも、プログラムの起動後に一度実行できるチェックの後ではありません。
これまでに使用したアプローチは次のとおりです。
従来の手続き型アプローチ:
従来のオブジェクト指向アプローチ (ビジター パターン):
シンプルなインターフェースアプローチ: