動的バインディング、遅延バインディング、動的リンケージとは
動的バインディング(dynamic binding)、遅延バインディング(late binding)、または動的リンケージ(dynamic linkage)とは、コンピュータプログラミングにおいて、オブジェクトに対して呼び出されるメソッドや、引数を伴って呼び出される関数を、その名前に基づいて実行時に探索するメカニズムを指します。これらはそれぞれ、動的束縛、遅延束縛、動的結合とも訳されます。
これらの用語は、動的ディスパッチの意味で使われることもあります。
静的バインディングとの比較
対義語となるのは、静的バインディング(static binding)または事前バインディング(early binding)です。静的バインディングでは、コンパイル時に確定した静的なオフセット情報などに基づいて、関数実体のアドレスを取得します。
動的バインディングの概要
静的型付けのプログラミング言語では、変数や式の型はコンパイル時に確定します。関数の存在確認も、コンパイル時にその名前や引数リストの型、所属する名前空間などに基づいて事前に検査されます。この、プログラマが記述した関数呼び出しを、実際に関数が実装されているコードに一致させるプロセスを「バインディング」と呼びます。
C++や
Javaといった
静的型付けのオブジェクト指向言語では、オブジェクトの型に基づいて実際に呼び出される関数(メソッド)が実行時に選択される「仮想関数」(仮想メソッド)を使った動的ディスパッチによって
ポリモーフィズムを実現します。
コンパイル時には、所望の関数を呼び出すためのアドレス情報が、プログラム内に
仮想関数テーブルにおけるメモリオフセットとして保持されます。実行時には、このメモリオフセット(関数ポインタ)を使って所望の関数が呼び出されます。この方式は、
仮想関数テーブルの構造が事前に分かっているという点で、事前バインディングの一種とも言えます。
遅延バインディング
遅延バインディングでは、
コンパイラは
仮想関数テーブルに所望の仮想関数が存在するかどうかを厳密には確認せず、代わりに名前を用いて実行時にルックアップします。これにより、
コンパイラがオブジェクトの型情報を含むライブラリ(DLL)を参照する必要がなくなるため、
Component Object Model (COM)プログラミングにおいて大きな利点となります。
遅延バインディングの利点と欠点
遅延バインディングの利点として、名前ベースの柔軟なプログラミングが可能になることで、ライブラリのバージョン衝突に対してコンパイル処理が強くなることが挙げられます。一方で、実行時に名前解決を行うため、
統合開発環境でのコード補完などの支援が受けられず、コンパイル時の静的な型チェックも行われません。そのため、実行時になって初めてプログラミングミスが発覚する可能性が高くなります。また、
コンパイラ最適化が働かず、オーバーヘッドが大きくなって実行速度が低下するというデメリットもあります。
動的プログラミング言語では、シンボル探索は基本的に名前ベースで実行時に解決する動的バインディング方式が採用されています。ダック・タイピングもこの一種です。
動的ディスパッチの例
C++では、仮想関数を派生クラスで
オーバーライドすることで、実際に呼び出される関数の実体をオブジェクトの型に応じて実行時に選択することができます。これが動的ディスパッチです。
cpp
class Base {
public:
virtual void someMethod() { /
Base class implementation / }
};
class Derived : public Base {
public:
void someMethod() override { /
Derived class implementation / }
};
int main() {
Base
obj1 = new Base();
Base obj2 = new Derived();
obj1->someMethod(); // Base::someMethodが呼び出される
obj2->someMethod(); // Derived::someMethodが呼び出される (動的ディスパッチ)
delete obj1;
delete obj2;
}
動的ディスパッチとバインディング
前述の通り、
仮想関数テーブルを利用した動的ディスパッチは、事前バインディングの一種です。しかし、動的ディスパッチの意味でこれらの用語が使われることもあります。
遅延バインディングの例
VB.NETにおける遅延バインディングの例を示します。
vbnet
' Option Strict Offの場合
Dim obj As Object
obj = CreateObject("Some.Object") ' 何らかのオブジェクトを作成
obj.SomeMethod() ' コンパイル時にはSomeMethodの存在チェックは行われない
VB.NETにおけるObject型は、.NETの基本クラス型であるSystem.Objectであり、あらゆる型の最上位基底クラスです。しかし、Object型自体には上記の`SomeMethod`という名前のメソッドは定義されていません。`Option Strict Off`を指定すると、コンパイル時にメソッドの存在有無を確認しなくなり、実行時に探索を試みます。これが遅延バインディングです。もし該当メソッドが見つからなかった場合、実行時に例外`System.MissingMemberException`がスローされます。
VB.NETの
コンパイラでは、デフォルトで`Option Strict Off`となっており、遅延バインディングが許可されています。
JavaやC#では、リフレクションを使って遅延バインディングを実現することもできます。C# 4.0以降は`dynamic`型を使用した遅延バインディングも可能です。
その他の遅延バインディングの例
- - Visual Basic .NET (VB.NET) では`Option Strict Off`によって遅延バインディングが可能。
- - Windows APIの`GetProcAddress()`や、POSIXの`dlsym()`は、関数名の文字列に基づいてモジュール内の関数ポインタを探索し、遅延バインディングを実現することができる。
まとめ
動的バインディング、遅延バインディング、動的リンケージは、プログラムの柔軟性を高めるための重要なメカニズムです。しかし、その特性を理解し、適切に使い分けることが重要です。
関連項目