問題タブ [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++ - 事前にすべてのクラスがわからない場合、二重ディスパッチを実装するにはどうすればよいですか?
(潜在的に) 多くのサブクラスを持つ基本クラスを持っています。基本クラスの任意の 2 つのオブジェクトが等しいかどうかを比較できるようにしたいと考えています。冒涜的な typeid キーワードを呼び出さずにこれを実行しようとしています。
equalityBounce() の lhs が Base* であるため、記述されたコードが失敗していることを理解しています。そのため、A* を受け取る equalityCheck() のバージョンについても認識していません。しかし、私はそれについて何をすべきかわかりません。
c++ - 二重ディスパッチによる循環依存
二重ディスパッチ パターンを実装しようとしていますが、前方宣言では解決できない循環依存関係が発生します (この問題のリンクで解決されているため)。
以下は私の問題の例です:
ヘッダー 1:
ヘッダー 2:
を使用するには完全な型が必要なため、ヘッダー 2 でBoundary
andを宣言することはできません。この問題を解決するためのアドバイスはありますか?Blockage
boost::unordered_set
smalltalk - ファロでのダブルディスパッチ
誰か、Pharo 4.0 の Smalltalk での二重ディスパッチのプロセスを説明してもらえますか? 私は Smalltalk を初めて使用し、Java での実装が Smalltalk とは大きく異なるため、概念を理解するのに苦労しています。誰かが例を挙げて説明できれば非常に役に立ちます。
c# - 動的なスパース ダブル ディスパッチ -- O(n^2) コードを使用せずに適切な方法はありますか?
私は次のものを持っています。できます。動的な使用を避け、コードが型の数で O(n^2) になるのを避ける方法でそれを行いたいです。私が認識している標準的な二重ディスパッチ ソリューションでは、タイプ A、B、C、D のそれぞれに O(n) コードがあり、全体として O(n^2) になります。
それを行うための正気の方法はありますか?
出力は次のとおりです。
背景については、ダブルディスパッチの代替案に関するこの質問を参照してください。
java - Java でのポリモーフィックな非カリー化メソッド呼び出し (アドホック ポリモーフィズム)
例から始めましょう。
抽象Vehicle
クラスがあるとします。
そして、この抽象クラスを継承するクラスCar
と。Bicycle
実際の型が実行時にしか決定できないride()
型のオブジェクトにメソッドを適用すると、JVM は正しいバージョンの を適用します。Vehicle
ride()
つまり、一種のカリー化されたメソッド呼び出しではv.ride()
、ポリモーフィズムが期待どおりに機能します。
Vehicle
しかし、引数として のサブタイプのみを受け入れるメソッドの形式で外部実装がある場合はどうなるでしょうか? では、repair(Bicycle b)
andrepair(Car c)
メソッドがある場合はどうなるでしょうか。カリー化されていないポリモーフィック メソッドの呼び出しrepair(v)
は機能しません。
例:
クラス名とダウンキャストを確認する必要があります。これに対するより良い解決策はありますか?
編集:私の実際の目的は、抽象構文ツリーをトラバースすることであり、たまたま二重ディスパッチが必要であることに気付きました。
Ast
Assign
、MethodCall
、またはReturnStmt
継承などの実際の AST ノードからの抽象クラスです。body
s の多相リストですAst
。
コードスニペット:
ダブルディスパッチを達成する唯一の可能性は、クラスをチェックしてダウンキャストするか、ビジターパターンを適切に実装することですよね?
java - ダブルディスパッチと継承
アウト プロセス ストレージの目的で文字列としてシリアル化したいダム オブジェクト クラスがいくつかあります。これは、ダブル ディスパッチ / ビジター パターンを使用するかなり典型的な場所です。
このモデルでは、データを保持するクラスは、そのデータをシリアル化する方法を知る必要がありません。JSON は 1 つのオプションですが、別のシリアライザーは、たとえば、データ クラスを SQL 挿入ステートメントに "シリアル化" する場合があります。
データ クラスの 1 つの実装を見ると、実装は他のすべてのものとほとんど同じに見えます。クラスは、渡されたserialize()
メソッドを呼び出し、それ自体を引数として提供します。Serializer
この共通コードを親クラスに取り込めない理由がわかりました。コードは共有されていますが、コンパイラはそのメソッド内に の型があることを明確に認識しており、this
(ExtFileSystemIdentifier
コンパイル時に) の最も型固有のオーバーロードを呼び出すためにバイトコードを書き出すことができますserialize()
。
V テーブル ルックアップに関しても、何が起こっているのかをほとんど理解していると思います。コンパイラは、serializer
パラメータが抽象型であることのみを認識しますSerializer
。serializer
実行時に、オブジェクトの 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 テーブル ルックアップを実行するためにランタイムに到達するまでに、探しているメソッドが間違っていて、ランタイムが を選択し、無限ループにつながることを意味します。Serializer
Serializer<T>
JsonSerializer.serialize(Serializable)
この問題の可能な解決策serialize
は、データ クラスでより型固有のメソッドを提供することです。
プログラム制御フローは、最も型固有のオーバーロードに達するまでバウンスしSerializer
ます。その時点で、インターフェイスには、プロジェクト A のデータ クラスに対するProjectASerializer<T>
より具体的なメソッドが含まれます。serialize
無限ループを回避。
これにより、二重発送の魅力がわずかに低下します。データ クラスの定型コードが増えました。二重ディスパッチのトリックを回避したため、明らかに重複したコードを親クラスに分解できないほど悪いことでした。現在、それはさらに多く、シリアライザーの継承の深さと相まって複雑になっています。
二重ディスパッチは、静的型付けの策略です。重複したコードを回避するのに役立つ静的型付けのトリックはありますか?
c++ - C++ 型比較: typeid と double ディスパッチ dynamic_cast
どちらかを優先するパフォーマンスまたは堅牢性の理由はありますか?
出力: