LINEスタンプ制作代行サービス・LINEスタンプの作り方!

お電話でのお問い合わせ:03-6869-8600

stampfactory大百科事典

ダブルディスパッチ

ダブルディスパッチ(英: double dispatch)は、多重ディスパッチのひとつの形態で、2個のオブジェクトから、それに対応する実際の手続きが決まる、というものである。近年のオブジェクト指向プログラミング言語でよく見られる obj.methodName(arg, ...) というような構文では、obj に対応する1個のオブジェクトから、実行されるメソッドが決定される「シングルディスパッチ」であるわけだが、それに対して複数個のオブジェクトが関与して、多重定義されたメソッドなどから、実行される一つが決定されるのが多重ディスパッチで、多重ディスパッチに関与するオブジェクトを2個に限定したものがダブルディスパッチである。また、シングルディスパッチの言語における複数のクラス間で同様のことを実現するイディオムを指して言う場合もある。たとえば、以下のような状況でダブルディスパッチを活用することができる。上記の例に現れる共通のイディオムは、呼び出しの引数の動的な型に応じた適切なアルゴリズムの選択である。したがって、動的に呼び出しを解決するために必要なパフォーマンス上のトレードオフが生じ、その影響はシングルディスパッチをサポートする言語よりも通常大きい。C++における動的な関数の呼び出しは、コンパイラがオブジェクトのメソッドテーブル(vtable)内の関数の位置を知っているため、静的にオフセットの演算を行うことで解決できる。ダブルディスパッチをサポートする言語では、メソッドのテーブル内のオフセットを動的に計算しなければならないため、よりコストが大きい。前述のように二項演算子という、(LispやForthなどを除いた)多くのプログラミング言語で好まれている機能において望まれるものであるため、シングルディスパッチのみがあるオブジェクト指向プログラミング言語でダブルディスパッチのようなふるまいを実現する手法が考えられている。ここでは一例としてRubyのものを示す。たとえばRubyに複素数クラスを自作して追加したいとする。Rubyでは二項演算子 codice_2 なども、左辺にあるオブジェクトに対するメソッド呼び出しなので、次のようなソースコードへの対応は自然に実装できる。これに対し、次のようにも書きたいわけだが、もし何も仕掛けが無ければ、あらゆる既存の数値クラスについて、「複素数を引数にした場合」を追加する必要があり現実的ではない。しかし、Rubyにおける数値関係のクラスの、演算子に対応するメソッドは次のようにふるまうようになっていて、追加したいクラス(たとえばここでは複素数クラス)に codice_3 というメソッドを一つ定義し、適切な値を返すようにすれば、任意の演算子に対して望んだような結果にできる。一見したところでは、ダブルディスパッチは関数のオーバーロードの自然な結果である。関数のオーバーロードは呼び出されるクラスだけではなく、引数の型にも応じて呼び出しが行われるようにすることができるが、オーバーロードされた関数の呼び出しはほぼ一つの仮想関数テーブルを通じて行われるため、動的なディスパッチは呼び出すオブジェクトの種類によってのみ決まる。下記の例において、あるゲームで衝突の判定を行う場合を考える。ここで、があるとすると、関数のオーバーロードのために上記のコードは、動的なディスパッチを使用せず、codice_4 およびcodice_5 とそれぞれ表示する。さらに、 上記のコードはcodice_6 およびcodice_7 と、やはり動的なディスパッチを使用せずに表示する。codice_8に対する参照を使って動的なディパッチを用いると、codice_6 およびcodice_7と期待通りに表示する。しかし、は、codice_4 および codice_6と表示するが、これはいずれも正しくない。問題は、仮想関数が C++ によって動的にディスパッチが行われるのに対して、関数のオーバーロードは静的に行われるためである。上述の問題は、Visitor パターンで用いられているものと同様の手法で解決できる。codice_13 と codice_14 がいずれも関数を持っているとすると、先ほどの例ではうまく動作しなかったが、以下の例はうまく動作する。この例は、期待通りにcodice_5 およびcodice_7と表示する。鍵はcodice_17 であり、これはランタイムに下記のような動作をする。

出典:wikipedia

LINEスタンプ制作に興味がある場合は、
下記よりスタンプファクトリーのホームページをご覧ください。