私はアーリーバインディングとレイトバインディングについて聞いていますが、それらが何であるかはわかりません。私は理解できない以下の説明を見つけました:
アーリーバインディングは、設計時の変数への値の割り当てを指し、レイトバインディングは、実行時の変数への値の割り当てを指します。
誰かが2つのタイプのバインディングを定義して、それらを比較してください。
混乱には、バインディングとロードという2つの主要な概念があります。それはDataBindingの概念によって融合されます。DataBindingは、途中でどこかで両方を実行することがよくあります。それを検討した後、もう1つのコンセプトを追加して、3部構成を完成させ、ディスパッチします。
遅延バインディング:タイプは不明です実行時に変数が実行されるまで;通常は割り当てによって行われますが、型を強制する他の方法もあります。動的に型付けされた言語はこれを基本的な機能と呼びますが、多くの静的に型付けされた言語には遅延バインディングを実現する方法がいくつかあります
[特別な]動的型、イントロスペクション/リフレクション、フラグ、コンパイラオプションを使用して、または動的ディスパッチを借用して拡張する仮想メソッドを介して実装されることが多い
アーリーバインディング:タイプは既知です実行時に変数が実行される前、通常は静的な宣言的手段
標準のプリミティブ型を使用して実装されることが多い
静的ディスパッチ:既知の特定の関数またはコンパイル時のサブルーチン。明確であり、署名と一致している
静的関数として実装されます。どのメソッドも同じシグネチャを持つことはできません
ダイナミックディスパッチ:特定の関数ではないまたはコンパイル時のサブルーチン。実行中のコンテキストによって決定されます。 「動的ディスパッチ」には2つの異なるアプローチがあり、適切な関数実装を選択するためにどのコンテキスト情報が使用されるかによって区別されます。
single [dynamic] dispatchでは、適切な関数の実装を決定するためにインスタンスのタイプのみが使用されます。静的型付き言語では、これが実際に意味することは、変数が宣言または割り当てられたときに示される参照型に関係なく、インスタンス型がどのメソッド実装を使用するかを決定することです。単一のタイプ(オブジェクトインスタンスのタイプ)のみが適切な実装の推定に使用されるため、このアプローチは「単一ディスパッチ」と呼ばれます。
multiple [dynamic] dispatchもあります。ここで、入力パラメーターのタイプは、呼び出す関数の実装の決定にも役立ちます。複数のタイプ(インスタンスの両方のタイプandパラメータのタイプ)が、選択されるメソッド実装に影響するため、このアプローチは「マルチディスパッチ」と呼ばれます。
仮想または抽象関数として実装されます。他の手がかりには、オーバーライドされた、隠された、またはシャドウされたメソッドが含まれます。
NB:メソッドのオーバーロードが動的ディスパッチを伴うかどうかは、言語固有です。たとえば、Javaでは、オーバーロードされたメソッドが静的にディスパッチされます。
遅延読み込み:必要になるまで値の割り当てを延期するオブジェクト初期化戦略;オブジェクトが本質的に有効であるが故意に不完全な状態になり、データをロードする前にデータが必要になるまで待機できるようにします。大規模なデータセットの読み込みや外部リソースの待機に特に役立つことが多い
いくつかのダウンストリーム呼び出し元がそのコレクションの内容を確認するように要求するまで(たとえば、get_value_at、get_all_asなど)、コンストラクターまたは初期化呼び出し中に、意図的にコレクションまたはリストを複合オブジェクトにロードしないことによって、しばしば実装されます。バリエーションには、コレクションに関するメタ情報(サイズやキーなど)の読み込みが含まれますが、実際のデータは省略されます。また、かなり安全で効率的なシングルトン実装スキームを開発者に提供するために、一部のランタイムにメカニズムを提供します
Eager Loading:すべての値の割り当てを即座に実行するオブジェクト初期化戦略自分自身がいると見なす前にすべてのデータを完了する必要がある有効な状態。
コンストラクターの呼び出しや初期化中など、既知のすべてのデータを含む複合オブジェクトをできるだけ早く提供することで実装されることが多い
データバインディング:多くの場合、2つの互換性のある情報ストリーム間のアクティブリンクまたはmapの作成により、一方への変更が他方に反映され、逆も同様です逆;互換性を保つために、多くの場合、共通の基本タイプまたはインターフェースが必要です。
さまざまなアプリケーションの側面(たとえば、ビューモデルからビュー、モデルからコントローラーなど)の間でよりクリーンで一貫性のある同期を提供する試みとしてしばしば実装され、ソースとターゲット、エンドポイント、バインド/アンバインド、更新、およびイベントなどの概念について話します。 on_bind、on_property_change、on_explicit、on_out_of_scope
編集上の注意:これらが頻繁に発生する例の説明を提供する最後の主要な編集。特定のコード例は完全に実装/ランタイム/プラットフォームに依存します
コンパイル中にコンパイラによって決定されるものはすべて、参照できますEARLY/COMPILE TIMEバインディングおよび[〜#〜] runtime [〜#〜]で決定されるものLATE/RUNTIMEバインディングと呼ばれます。
例えば、
メソッドOverloadingおよびメソッドOverriding。
1)Method Overloadingでは、メソッドへのメソッド呼び出しは、呼び出される関数がコンパイラーによってコンパイル時に決定されるという意味で、コンパイラーによって決定されます。したがってEARLY BINDINGになります。
2)メソッドOverridingでは、どのメソッドが呼び出されるかはRUNTIMEで決定されます。したがって、それはLATE BINDINGとして参照されます。
シンプルで簡単に入手できるようにしようとしました。お役に立てれば。
レイトバインディングとは、動作が実行時に評価されるときです。実際に、プログラムの実行中にのみ得られる情報に基づいて行動する方法を決定したい場合に必要です。私の意見で最も明確な例は、特にC++の仮想関数メカニズムです。
_class A
{
public:
void f() {}
virtual void g() {}
};
class B : public A
{
void f() {}
virtual void g() {}
};
int main()
{
A* a = new B;
a->f();
a->g();
}
_
この例では、a->f()
は実際にはvoid A::f()
を呼び出します。これは、プログラムが早期(または静的)にバインドされているため、実行時のプログラムthinksへのポインタにすぎないためです。 A
タイプの変数ですが、a->g()
は実際にはvoid B::g()
を呼び出します。これは、コンパイラがg()
を仮想であると見なすため、コードを挿入して実行時に呼び出す正しい関数のアドレス。
関数ポインタに慣れている場合、これは一例です。定義された関数は、事前バインディングであると言えます。一方、関数ポインタを使用する場合、その遅延バインディング。
int add(int x,int y)
{
return x+y;
}
int sub(int x,int y)
{
return x-y;
}
int main()
{
//get user choice
int(*fp)(int,int);
//if add
fp=add;
//else if sub
fp=sub;
cout<<fp(2,2);
}
ここで関数addとsubは関数です(そのアドレスはコンパイル時にリンカーにバインドされます)
しかし、関数ポインタは遅延バインディングであり、fpはユーザーの選択に応じて[実行時] addまたはsubを呼び出すことができます。
アーリーバインディングとレイトバインディングは、型のコンテキストでのみ意味があり、型の説明では意味がありません。ほとんどすべての現代の言語は、すべての値に固定型があるという意味で型付けされています。動的型と静的型付きの言語を比較すると、違いがあります。動的に型付けされた言語では、変数には型がないため、任意の型の値を参照できます。つまり、変数によって参照されるオブジェクトのメソッドを呼び出すとき、その呼び出しが有効かどうかを判断する唯一の方法は、オブジェクトのクラスを検索し、そのメソッドが実際に存在するかどうかを確認します。これにより、実際のメソッド検索が最後まで延期されるため、実行時にクラスに新しいメソッドを追加するなどのクールなことが可能になります。ほとんどの人はこの状態を拘束力のある人と呼びます。
静的に型付けされた言語では、変数は型を持ち、一度宣言されると、同じ型ではない値を参照できません。これは厳密には当てはまりませんが、とりあえず仮定します。変数が特定の型の値のみを参照することがわかっている場合は、コードが実行される前に有効性を判断できるため、実行時にメソッド呼び出しが有効かどうかを判断する理由はありません。これは事前バインディングと呼ばれます。
Rubyで遅延バインディングを示す例:
a = 1 # a is an integer at this point
a.succ # asking for its successor is valid
class A
def method_a
# some code
end
end
a = A.new
a.method_a # this is also valid
a.succ # this is not valid
class A # we can re-open the class and add a method
def succ
# some more code
end
end
a.succ # now this is valid
上記の一連のアクションは、Javaなどの言語では実行時にすべてのタイプが固定されるため、不可能です。
アカデミックな定義を与える代わりに、VBAを使用した実際の例を使用して、いくつかの違いを示します。
早期バインディング:
Dim x As FileSystemObject
Set x = New FileSystemObject
Debug.Print x.GetSpecialFolder(0)
設計時で「Microsoft Scripting Runtime」コンポーネントに参照を設定する必要があります。 FileSystemObject
にタイプミスがある場合やGetSpecialFolder
のようなメソッド名がある場合は、コンパイル時にエラーメッセージが表示されるという利点があります。
遅延バインディング
Dim x As Object
Set x = CreateObject("Scripting.FileSystemObject")
Debug.Print x.GetSpecialFolder(0)
これは、参照を事前に設定する必要はありません。インスタンスの作成とタイプの決定は、実行時に行われます。 x
の存在しないメソッドを呼び出そうとすると、コンパイラはコンパイル時に文句を言わず、特定の行が実行されたときにのみ実行時エラーが発生します。
したがって、遅延バインディングの欠点は、ここでは強力な型チェックがないことです。しかし、それも利点です。たとえば、複数のバージョンが存在するコンポーネントがあり、新しいバージョンごとにいくつかの追加機能が提供されているとします。 (実際の例は、Excel COMインターフェイスのようなMS Officeコンポーネントです)遅延バインディングを使用すると、そのすべてのバージョンと連携するコードを記述できます。最初に特定のコンポーネントのバージョンを判別できます。古いバージョンのみが利用可能です。そのバージョンでは機能しない関数呼び出しを実行しないでください。