ビジターパターンについて読んでいますが、ダブルディスパッチと同じように見えます。2つの間に違いはありますか?2つの用語を実行することは同じことを意味します。
5 に答える
要するに
それらは、ダブルディスパッチがネイティブにサポートされていない一部の言語では、マルチディスパッチサロゲートを持つために2つ(またはそれ以上)のシングルディスパッチを連結する方法としてビジターパターンにつながるさまざまな概念化に由来します。
長い間
多重ディスパッチの考え方は、基本的に、次のような呼び出しを許可することです。
void fn(virtual base_a*, virtual base_b*);
(注:クラスメンバーとしてではありません:これはC ++ではありません!)
これは次のようにオーバーライドできます
void fn(virtual derived_a1*, virtual derived_b1*);
void fn(virtual derived_a2*, virtual derived_b1*);
void fn(virtual derived_a1*, virtual derived_b2*);
void fn(virtual derived_a2*, virtual derived_b2*);
だから、呼び出すとき
fn(pa, pb)
呼び出しは、との両方の実際のランタイムタイプに一致するオーバーライドにリダイレクトされます。(これは、任意の数のパラメーターに一般化できます)pa
pb
C ++、C#、Javaなどの言語では、このメカニズムは存在せず、実行時型ディスパッチは基本的に1つのパラメーターで機能します(つまり、関数自体をクラスのメンバーにすることで、関数内で暗黙的になります。
言い換えれば、擬似コード
void fn(virtual base_a*, base_b*)
(実際のC ++)になります
class base_a
{
public:
virtual void fn(base_b*);
}
ここではvirtual
、の前にこれ以上ないことに注意してくださいbase_b
。これからは静的になります。のような呼び出し
pa->fn(pb)
paがderived_a2を指し、pbがderived_b1を指す場合、derived_a2 :: fn(derived_b1 *)がそこにあるかどうかに関係なく、derived_a2 :: fn(base_b *)にディスパッチされます。 pbによるものは考慮されません。
ビジターパターンの考え方は、別のオブジェクトの仮想ディスパッチを呼び出す(最終的には戻す)オブジェクトの仮想ディスパッチを呼び出すことです。
class base_a
{
public:
virtual void fn(base_b*)=0;
virtual void on_visit(derived_b1*)=0;
virtual void on_visit(derived_b2*)=0;
};
class base_b
{
public:
virtual void on_call(derived_a1*)=0;
virtual void on_call(derived_a2*)=0;
};
//forward declarations, to allow pointers free use in other decls.
class derived_a1;
class derived_b1;
class derived_a1: public base_a
{
public:
virtual void fn(base_b* pb) { pb->on_call(this); }
virtual void on_visit(derived_b1* p1) { /* useful stuff */ }
...
};
class derived_b1: public base_b
{
public:
virtual void on_call(derived_a1* pa1) { pa1->on_visit(this); }
...
};
pa->fn(pb)
これで、 paがderived_a1を指し、pbがderived_b1を指す場合、のような呼び出しは最終的にになりderived_a1::on_visit(derived_b1*)
ます。
ビジターパターンは、ダブルディスパッチの動作を実装するソリューションの1つです。他にもいくつかの解決策があります。ダブルディスパッチという用語自体は解決策のアイデアを与えません。実際、それは訪問者パターンによって解決策が提供される問題です。
C#(4.0)では、dynamic
キーワードを使用してダブルディスパッチを実装できます。この場合、ビジターパターンは必要ありません。キーワードを使用したダブルディスパッチの問題に対する私の解決策は次のとおりです。dynamic
動的ディスパッチとは、一般に、実行時情報に基づいてメソッドにディスパッチするという概念を指します。ほとんどのオブジェクト指向システム(Java / C#/ C ++など)は通常、virtual
メソッドを介して動的ディスパッチを実装します(すべてのメソッドが仮想であるかどうかは言語に依存します)。これにより、単一のメソッド引数(暗黙的なオブジェクト参照)に従ってディスパッチするように制限されます。
一般に、任意の数の要素に従ってディスパッチすることができます。たとえば、ダブルディスパッチは、メソッドの2つの引数に従ってディスパッチするための要件/機能です。
一方、Visitor Patternは、一般にマルチディスパッチの実装であり、したがって、特にそのようなOOシステムではダブルディスパッチです。
ダブルディスパッチは技術的な問題であり、言語によってはさまざまな方法で解決できます。一部の言語では、ダブルディスパッチを直接サポートしています。ビジターパターンは、さまざまな問題を解決するために使用できるパターンです。C ++の場合、これはダブルディスパッチに使用される最も頻繁な(ただし唯一ではない)ソリューションですが、それだけに使用されるわけではなく、ダブルディスパッチをサポートする言語でも役立ちます。