問題タブ [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# - 動的二重ディスパッチの前に型の可視性をチェックする
を使用して二重ディスパッチを実装するdynamic
:
ほとんどの場合に機能します:
1つ完成
2つ完成
ただし、サブクラスがディスパッチ コードから見えない場合は、実行時エラーが発生します。
RuntimeBinderException
型「オブジェクト」は、ジェネリック型またはメソッド「DomainEventDispatcher.Publish(TEvent)」の型パラメーター「TEvent」として使用できません
これは不自然な例です。より現実的なものは、別のアセンブリの内部にあるイベントです。
この実行時例外を防ぐにはどうすればよいですか? それが不可能な場合、Subscribe
メソッドでこのケースを検出してすばやく失敗するにはどうすればよいですか?
編集:動的キャストを排除するソリューションは、すべてのサブクラスを認識しているビジター スタイルのクラスを必要としない限り、許容されます。
c# - 動的型への C# キャストに相当する C++/CLI はありますか?
ここで説明されているように、dynamic キーワードを使用してビジター パターン (ダブル ディスパッチ) を実装する C# で記述されたクラス階層を拡張しています。
これは、私が現在 C# で行っていることの非常に単純化された疑似コードです。
ここで、階層を拡張すると、派生クラスはCommand
、基本クラスが認識していない新しい特殊化を処理する必要がある場合があります。この場合、二重ディスパッチは失敗します(動的なオーバーロードの解決は、メソッドを一致させようとしているときに、拡張されたクラス階層を走査しないようです)。これには簡単な修正方法があり (以前にリンクされた記事で説明されています)、次のように、派生クラスのメソッドをオーバーライドするAcceptCommand()
(元の実装を複製する) ことで構成されます。
最近、便宜上、C++/CLI で実装されたプロジェクトのクラスを使用して階層を拡張する必要がありました (アンマネージ WIN32 API コードとの多くのやり取り)。このプロジェクトではいくつかのCommand
特殊化が導入さAcceptCommand()
れたため、二重ディスパッチを修正するために C# で行っているように C++/CLI クラスのメソッドをオーバーライドする必要がありますが、問題はオブジェクトのキャストを実行する方法がわからないことです。Command
C++/CLI 構文の動的型。これは可能ですか?
java - Java の二重ディスパッチによって無限ループが発生しないのはなぜですか?
講義では、このコードを見せられ、二重ディスパッチが作成されると説明されましたが、なぜ無限ループが作成されないのですか?
もし c3po.greet(c4po); TranslationRobot から TranslationRobot メソッドを呼び出します
なぜc5po.greet(c4po); TranslationRobot メソッドではなく CarrierRobot で AbstractRobot メソッドを呼び出してから、TranslationRobot で AbstractRobot メソッドを呼び出さないと、CarrierRobot で AbstractRobot メソッドが呼び出されますか?
AbstractRobot メソッドを呼び出すかどうかを決定するものは何ですか?
AbstractRobot.java
CarrierRobot.Java
TranslationRobot.Java
DispatchWorld.Java
これにより、次の出力が生成されます。
c++ - ダブルディスパッチと静的ポリモーフィズムの混合
これは悪い考えだと確信しています。そうする正当な理由があるふりをしましょう。静的ポリモーフィズムを使用してメッセージを渡すノードのツリーがあります。重要なことに、各ノードは接続先のノードのタイプを知ることはできず、渡すメッセージのタイプを知っているだけです。ツリーをトラバースするために、CRTP を使用してビジター パターンを実装しました。これは、ツリーの最初のレベルで機能します。
ただし、ツリーの 2 番目のレイヤーにトラバースすると、次のノードのタイプは以下の AnyNode クラスを使用して消去されます。消去された型から具体的な型にダウンキャストする方法を理解できませんでした。以下の例はテストで機能しますが、おそらく非常に危険であり、たまたまメモリが配置されている場所の運だけで機能していると思います。
AnyNode::Model<T>::acceptDispatch
で完全にわかっているの訪問者の型を消去しなければならないのは問題があるようAnyNode::Concept::accept
です。しかし、コンセプトからコンセプトのモデルにダウンキャストする方法がわかりません(共変仮想cast
関数を試しましたが、うまくいきませんでした)。また、仮想メソッドをテンプレート化できないため、型指定された Visitor を仮想メソッドを使用して派生 Model クラスに渡すことはできません。
node.accept
ビジターのタイプを消去してから静的にキャストし直すことなく、ビジターを呼び出して渡す安全な方法はありますか? Model<T>
実行時にコンセプトをダウンキャストする方法はありますか? この問題にアプローチするより良い方法はありますか? おそらくSFINAEを使用して、これを解決するクレイジーな新しいC++ 11の方法はありませんか?
編集ここにビジター基本クラスと、派生ビジターの例があります。派生した Visitor はクライアント コード (これはライブラリの一部です) によって実装されるため、基本クラスはどの Visitor が実装されるかを知ることができません。これが中心的な質問から気をそらしてしまうのではないかと思いますが、問題を少し説明するのに役立つことを願っています. ->accept( visitor )
の AnyNode ポインタで が呼び出された場合を除き、ここにあるものはすべて機能しますoutlet_visitor::operator()
。
c++ - Visitor パターンで accept() が必要な理由と、visitor.visit() を直接呼び出すことができない理由
少し前に使った Visitor パターンを修正しています。仮想メソッドaccept(Visitor)を持つ基本クラスElementがあり、このメソッドはElementから継承するすべてのクラスでオーバーライドされます。また、任意の派生クラスで accept() が行うことは、visitor->visit(*this) を呼び出すことだけです。クライアントがコードを実行すると、たとえば次のようになります。
クライアントが次のように Visitor->visit(element) を呼び出すことができない理由:
element.accept(visitor) を呼び出して、それが次に visitor.visit(element) を呼び出す場合に役立つ情報は何ですか? これにより、Visitor パターンの使用が煩雑になり、Element クラスのすべての階層で追加のコードが必要になります。
では、誰かがここで accept() の利点を説明できますか?