問題タブ [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 投票する
3 に答える
649 参照

c++ - 事前にすべてのクラスがわからない場合、二重ディスパッチを実装するにはどうすればよいですか?

(潜在的に) 多くのサブクラスを持つ基本クラスを持っています。基本クラスの任意の 2 つのオブジェクトが等しいかどうかを比較できるようにしたいと考えています。冒涜的な typeid キーワードを呼び出さずにこれを実行しようとしています。

equalityBounce() の lhs が Base* であるため、記述されたコードが失敗していることを理解しています。そのため、A* を受け取る equalityCheck() のバージョンについても認識していません。しかし、私はそれについて何をすべきかわかりません。

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

c++ - 二重ディスパッチによる循環依存

二重ディスパッチ パターンを実装しようとしていますが、前方宣言では解決できない循環依存関係が発生します (この問題のリンクで解決されているため)。

以下は私の問題の例です:

ヘッダー 1:

ヘッダー 2:

を使用するには完全な型が必要なため、ヘッダー 2 でBoundaryandを宣言することはできません。この問題を解決するためのアドバイスはありますか?Blockageboost::unordered_set

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

smalltalk - ファロでのダブルディスパッチ

誰か、Pharo 4.0 の Smalltalk での二重ディスパッチのプロセスを説明してもらえますか? 私は Smalltalk を初めて使用し、Java での実装が Smalltalk とは大きく異なるため、概念を理解するのに苦労しています。誰かが例を挙げて説明できれば非常に役に立ちます。

0 投票する
0 に答える
112 参照

c# - 動的なスパース ダブル ディスパッチ -- O(n^2) コードを使用せずに適切な方法はありますか?

私は次のものを持っています。できます。動的な使用を避け、コードが型の数で O(n^2) になるのを避ける方法でそれを行いたいです。私が認識している標準的な二重ディスパッチ ソリューションでは、タイプ A、B、C、D のそれぞれに O(n) コードがあり、全体として O(n^2) になります。

それを行うための正気の方法はありますか?

出力は次のとおりです。

背景については、ダブルディスパッチの代替案に関するこの質問を参照してください。

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

java - Java でのポリモーフィックな非カリー化メソッド呼び出し (アドホック ポリモーフィズム)

例から始めましょう。

抽象Vehicleクラスがあるとします。

そして、この抽象クラスを継承するクラスCarと。Bicycle

実際の型が実行時にしか決定できないride()型のオブジェクトにメソッドを適用すると、JVM は正しいバージョンの を適用します。Vehicleride()

つまり、一種のカリー化されたメソッド呼び出しではv.ride()、ポリモーフィズムが期待どおりに機能します。

Vehicleしかし、引数として のサブタイプのみを受け入れるメソッドの形式で外部実装がある場合はどうなるでしょうか? では、repair(Bicycle b)andrepair(Car c)メソッドがある場合はどうなるでしょうか。カリー化されていないポリモーフィック メソッドの呼び出しrepair(v)は機能しません。

例:

クラス名とダウンキャストを確認する必要があります。これに対するより良い解決策はありますか?


編集:私の実際の目的は、抽象構文ツリーをトラバースすることであり、たまたま二重ディスパッチが必要であることに気付きました。

AstAssignMethodCall、またはReturnStmt継承などの実際の AST ノードからの抽象クラスです。bodys の多相リストですAst

コードスニペット:

ダブルディスパッチを達成する唯一の可能性は、クラスをチェックしてダウンキャストするか、ビジターパターンを適切に実装することですよね?

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

java - ダブルディスパッチと継承

アウト プロセス ストレージの目的で文字列としてシリアル化したいダム オブジェクト クラスがいくつかあります。これは、ダブル ディスパッチ / ビジター パターンを使用するかなり典型的な場所です。

このモデルでは、データを保持するクラスは、そのデータをシリアル化する方法を知る必要がありません。JSON は 1 つのオプションですが、別のシリアライザーは、たとえば、データ クラスを SQL 挿入ステートメントに "シリアル化" する場合があります。

データ クラスの 1 つの実装を見ると、実装は他のすべてのものとほとんど同じに見えます。クラスは、渡されたserialize()メソッドを呼び出し、それ自体を引数として提供します。Serializer

この共通コードを親クラスに取り込めない理由がわかりました。コードは共有されていますが、コンパイラはそのメソッド内に の型があることを明確に認識しており、this(ExtFileSystemIdentifierコンパイル時に) の最も型固有のオーバーロードを呼び出すためにバイトコードを書き出すことができますserialize()

V テーブル ルックアップに関しても、何が起こっているのかをほとんど理解していると思います。コンパイラは、serializerパラメータが抽象型であることのみを認識しますSerializerserializer実行時に、オブジェクトの V テーブルを調べてserialize()、特定のサブクラスのメソッドの場所を検出する必要があります。この場合は、JsonSerializer.serialize()

典型的な使用法は、 であることが知られているデータ オブジェクトを取得し、Serializableそれを であることが知られているシリアライザ オブジェクトに与えることによってシリアライズすることSerializerです。オブジェクトの特定の型は、コンパイル時にはわかりません。

このインスタンスは、他の呼び出しと同様に機能しますが、逆になります。

のインスタンスで V テーブル ルックアップが実行され、たとえばSerializableが検出されますExtFileSystemIdentifier.serialize。最も近い一致するオーバーロードが for であることを静的に判断できますSerializer<T>(たまたま唯一のオーバーロードでもあります)。

これはすべて順調です。これにより、入力および出力データ クラスがシリアライゼーション クラスに気付かないようにするという主な目標が達成されます。また、シリアライゼーションの種類に関係なく、シリアライゼーション クラスのユーザーに一貫した API を提供するという第 2 の目標も達成します。

別のプロジェクトにダム データ クラスの 2 番目のセットが存在するとします。これらのオブジェクト用に新しいシリアライザーを作成する必要があります。この新しいプロジェクトでは、既存のSerializableインターフェイスを使用できます。ただし、Serializerインターフェイスには、他のプロジェクトからのデータ クラスへの参照が含まれています。

これを一般化するために、Serializerインターフェイスを 3 つに分割できます。

このようにして、SerializerおよびSerializableインターフェースをパッケージ化して再利用することができます。ただし、これにより二重ディスパッチが中断され、コード内で無限ループが発生します。これは、V テーブル ルックアップで不明な部分です。

serializeデバッガーでコードをステップ実行すると、データ クラスのメソッドで問題が発生します。

私が考えているのは、コンパイル時に、コンパイラーがインターフェイスserializeで使用可能なオプションからメソッドの正しいオーバーロードを選択しようとしているということです (コンパイラーはそれを としてのみ認識しているため)。これは、V テーブル ルックアップを実行するためにランタイムに到達するまでに、探しているメソッドが間違っていて、ランタイムが を選択し、無限ループにつながることを意味します。SerializerSerializer<T>JsonSerializer.serialize(Serializable)

この問題の可能な解決策serializeは、データ クラスでより型固有のメソッドを提供することです。

プログラム制御フローは、最も型固有のオーバーロードに達するまでバウンスしSerializerます。その時点で、インターフェイスには、プロジェクト A のデータ クラスに対するProjectASerializer<T>より具体的なメソッドが含まれます。serialize無限ループを回避。

これにより、二重発送の魅力がわずかに低下します。データ クラスの定型コードが増えました。二重ディスパッチのトリックを回避したため、明らかに重複したコードを親クラスに分解できないほど悪いことでした。現在、それはさらに多く、シリアライザーの継承の深さと相まって複雑になっています。

二重ディスパッチは、静的型付けの策略です。重複したコードを回避するのに役立つ静的型付けのトリックはありますか?

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

c++ - C++ 型比較: typeid と double ディスパッチ dynamic_cast

どちらかを優先するパフォーマンスまたは堅牢性の理由はありますか?

出力: