Was ist Früh- und Spätbindung?


77

Ich höre immer wieder von früher und später Bindung, aber ich verstehe nicht, was sie sind. Ich habe die folgende Erklärung gefunden, die ich nicht verstehe:

Eine frühe Bindung bezieht sich auf die Zuweisung von Werten zu Variablen während der Entwurfszeit, während sich eine späte Bindung auf die Zuweisung von Werten zu Variablen während der Laufzeit bezieht.

Könnte jemand bitte die beiden Bindungsarten definieren und vergleichen?


1
Kompilierzeit vs. Laufzeit.
Barlop

Antworten:


84

Es gibt zwei Hauptkonzepte in der Verwirrung: Binden und Laden. Es wird durch das Konzept von DataBinding zusammengeführt, das irgendwo in der Mitte ist und oft beides tut. Nachdem ich darüber nachgedacht habe, werde ich ein weiteres Konzept hinzufügen, um die Trifecta zu vervollständigen, den Versand.

Typen

Late Binding : Der Typ ist unbekannt, bis die Variable zur Laufzeit ausgeführt wird. normalerweise durch Zuweisung, aber es gibt andere Mittel, um einen Typ zu erzwingen; Dynamisch typisierte Sprachen nennen dies eine zugrunde liegende Funktion, aber viele statisch typisierte Sprachen verfügen über eine Methode zum Erreichen einer späten Bindung

Wird häufig mithilfe von [speziellen] dynamischen Typen, Introspection / Reflection, Flags und Compiler-Optionen oder durch virtuelle Methoden durch Ausleihen und Erweitern des dynamischen Versands implementiert

Frühes Binden : Der Typ ist bekannt, bevor die Variable zur Laufzeit ausgeführt wird, in der Regel statisch und deklarativ

Wird häufig mit Standardprimitivtypen implementiert

Funktionen

Statischer Versand : bekannte, spezifische Funktion oder Subroutine zur Kompilierzeit; es ist eindeutig und entspricht der Signatur

Implementiert als statische Funktionen; Keine Methode kann dieselbe Signatur haben

Dynamischer Versand : Keine bestimmte Funktion oder Unterroutine zur Kompilierungszeit. während der Ausführung durch den Kontext bestimmt. Es gibt zwei verschiedene Ansätze für "dynamisches Versenden", die sich dadurch unterscheiden, welche Kontextinformationen zur Auswahl der geeigneten Funktionsimplementierung verwendet werden.

Bei einem einzelnen [ dynamischen ] Versand wird nur der Typ der Instanz verwendet, um die entsprechende Funktionsimplementierung zu bestimmen. In statisch typisierten Sprachen bedeutet dies in der Praxis, dass der Instanztyp entscheidet, welche Methodenimplementierung verwendet wird, unabhängig vom Referenztyp, der beim Deklarieren / Zuweisen der Variablen angegeben wird. Da nur ein einzelner Typ - der Typ der Objektinstanz - verwendet wird, um die entsprechende Implementierung abzuleiten, wird dieser Ansatz als "einzelner Versand" bezeichnet.

Es gibt auch mehrere [ dynamische ] Dispatches , bei denen Eingabeparametertypen auch helfen, die aufzurufende Funktionsimplementierung zu bestimmen. Da mehrere Typen - sowohl der Typ der Instanz als auch der Typ der Parameter - Einfluss darauf haben, welche Methodenimplementierung ausgewählt wird, wird dieser Ansatz als "Mehrfachversand" bezeichnet.

Als virtuelle oder abstrakte Funktionen implementiert; Andere Hinweise sind überschriebene, versteckte oder schattierte Methoden.

Hinweis: Ob das Überladen von Methoden einen dynamischen Versand beinhaltet oder nicht, ist sprachspezifisch. In Java werden beispielsweise überladene Methoden statisch verteilt.

Werte

Lazy Loading : Objektinitialisierungsstrategie, die die Wertzuweisung aufschiebt, bis sie benötigt wird ; ermöglicht es einem Objekt, sich in einem im Wesentlichen gültigen, aber wissentlich unvollständigen Zustand zu befinden und zu warten, bis die Daten benötigt werden, bevor es geladen wird; Wird oft als besonders nützlich zum Laden großer Datensätze oder zum Warten auf externe Ressourcen angesehen

Wird häufig implementiert, indem eine Sammlung oder Liste während des Konstruktor- oder Initialisierungsaufrufs nicht absichtlich in ein zusammengesetztes Objekt geladen wird, bis ein nachgeschalteter Aufrufer den Inhalt dieser Sammlung abfragt (z. B. get_value_at, get_all_as usw.). Variationen beinhalten das Laden von Metainformationen über die Sammlung (wie Größe oder Schlüssel), aber das Weglassen der tatsächlichen Daten; bietet auch einen Mechanismus für einige Laufzeiten, um Entwicklern ein ziemlich sicheres und effizientes Singleton-Implementierungsschema zur Verfügung zu stellen

Eager Loading : Objektinitialisierungsstrategie, die alle Wertzuweisungen sofort ausführt , damit alle erforderlichen Daten vollständig sind, bevor sie als gültig eingestuft werden.

Wird häufig implementiert, indem zusammengesetzte Objekte wie bei einem Konstruktoraufruf oder einer Initialisierung so schnell wie möglich mit allen bekannten Daten versorgt werden

Datenbindung : Häufig wird ein aktiver Link oder eine Karte zwischen zwei kompatiblen Informationsströmen erstellt, sodass Änderungen an einem in den anderen zurückgespiegelt werden und umgekehrt. Um kompatibel zu sein, müssen sie häufig einen gemeinsamen Basistyp oder eine gemeinsame Schnittstelle haben

Wird häufig implementiert, um eine sauberere, konsistente Synchronisation zwischen verschiedenen Anwendungsaspekten (z. B. Ansichtsmodell zu Ansicht, Modell zu Steuerung usw.) zu gewährleisten und Konzepte wie Quelle und Ziel, Endpunkte, Binden / Aufheben, Aktualisieren und Ereignisse wie zu beschreiben on_bind, on_property_change, on_explicit, on_out_of_scope


BEARBEITUNGSHINWEIS: Letzte größere Bearbeitung, um Beispiele für deren häufiges Auftreten zu beschreiben. Bestimmte Codebeispiele hängen vollständig von der Implementierung / Laufzeit / Plattform ab


2
Diese Antwort scheint für objektorientierte Sprachen zu spezifisch zu sein.
Jack

27

Alles, was vom Compiler während des Kompilierens entschieden wird, kann als EARLY / COMPILE TIME Binding bezeichnet werden, und alles, was bei RUNTIME entschieden werden soll, wird als LATE / RUNTIME Binding bezeichnet.

Zum Beispiel,

Verfahren Overloading und Verfahren überschreiben .

1) Beim Überladen von Methoden werden die Methodenaufrufe vom Compiler in dem Sinne festgelegt, dass der Compiler beim Kompilieren festlegt, welche Funktion aufgerufen werden soll. Daher ist es FRÜH BINDEND .

2) In der Methode Overriding wird bei RUNTIME entschieden, welche Methode aufgerufen wird. Es wird also als LATE BINDING bezeichnet .

Versucht, es einfach und leicht zu bekommen. Hoffe das hilft.


9

Eine späte Bindung liegt vor, wenn das Verhalten zur Laufzeit ausgewertet wird. Dies ist erforderlich, wenn Sie in der Tat bestimmen möchten, wie Sie auf der Grundlage von Informationen vorgehen sollen, die Sie nur haben, wenn das Programm ausgeführt wird. Das meiner Meinung nach klarste Beispiel ist der virtuelle Funktionsmechanismus, speziell in 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();
}

In diesem Beispiel a->f()wird tatsächlich aufgerufen void A::f(), weil es zu früh (oder statisch) gebunden ist, und das Programm zur Laufzeit denkt, es sei nur ein Zeiger auf eine ATypvariable, wohingegen a->g()tatsächlich aufgerufen wird void B::g(), weil der Compiler, der sieht, g()virtuellen Code einfügt, um zu schauen Rufen Sie zur Laufzeit die Adresse der richtigen Funktion auf.


1
"Die Laufzeit"? Sie sprechen von C ++. C ++ kompiliert direkt in Maschinencode. Es ist keine Laufzeit erforderlich, um virtuelle Methoden aufzulösen.
tdammers

3
@tdammers C ++ benötigt tatsächlich eine Laufzeitbibliothek, jedoch nicht für virtuelle Aufrufe. Wenn Sie sorgfältig lesen, werden Sie feststellen, dass diese Antwort besagt, dass der Compiler "Code einfügt, um zur Laufzeit die Adresse der richtigen [...] Funktion zu ermitteln ".

Nun, aber dieser "Code zum Nachschlagen der Adresse der richtigen Funktion" ist im Grunde genommen nur eine typunabhängige zweistufige Zeiger-Dereferenzierung, gefolgt von einem Funktionsaufruf. Es ist kein "Denken" involviert; Der einzige Grund, warum es zuverlässig funktioniert, ist, dass der Compiler die Typprüfung zur Kompilierungszeit durchführt . Zur Laufzeit vertraut der generierte Code darauf, dass der Compiler die Hausaufgaben für die Typprüfung erledigt hat. Wenn Sie unsicher Abgüsse (zB C-Stil Zeiger wirft) verwenden, Sie können rechtlich C ++ Objekte als Ziel der falschen Klasse behandeln, aber ihre vtables wird völlig verkorkste und der Code nur bricht.
Tdammers

@tdammers Ich habe versucht, mich von dieser Art von Antworten fernzuhalten, da es sich um ein Implementierungsdetail von Compilern handelt, das für einige esoterische Compiler möglicherweise zutrifft oder nicht. Was zählt, ist das Konzept.
Yam Marcovic

1
@tdammers Und mit "der Laufzeit" meine ich "das Programm zur Laufzeit". Offensichtlich wird C ++ nicht verwaltet. Aber da Sie mir gezeigt haben, dass es Verwirrung stiften kann, ändere ich es auf den vollen Wortlaut.
Yam Marcovic

5

Wenn Sie mit Funktionszeigern vertraut sind, wäre dies ein Beispiel. Die definierten Funktionen können als Frühbindung bezeichnet werden. Wenn Sie Funktionszeiger verwenden, wird die späte Bindung verwendet.

  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);
    }

hier sind Funktionen add und sub Funktionen (ihre Adresse wird beim Kompilieren gebunden)

Der Funktionszeiger ist jedoch zu spät gebunden. Der fp kann je nach Benutzerauswahl [zur Laufzeit] entweder add oder sub aufrufen.


3

Frühe und späte Bindung sind nur im Kontext von Typen sinnvoll und nicht in der Art, wie Sie sie beschreiben. Fast alle modernen Sprachen werden in dem Sinne getippt, dass alle Werte feste Typen haben. Der Unterschied ergibt sich aus der Betrachtung von dynamisch gegenüber statisch getippten Sprachen. In dynamisch getippten Sprachen haben Variablen keine Typen, sodass sie auf Werte eines beliebigen Typs verweisen können. Wenn Sie also eine Methode für ein Objekt aufrufen, auf das eine Variable verweist, können Sie nur mit bestimmen, ob dieser Aufruf gültig ist oder nicht Suchen Sie in der Klasse nach dem Objekt und prüfen Sie, ob diese Methode tatsächlich vorhanden ist. Dies ermöglicht einige coole Dinge wie das Hinzufügen neuer Methoden zu Klassen zur Laufzeit, da die eigentliche Methodensuche bis zum allerletzten Moment zurückgestellt wird. Die meisten Menschen bezeichnen diesen Sachverhalt als verspätet.

In einer statisch typisierten Sprache haben Variablen Typen und können sich nach der Deklaration nicht auf Werte beziehen, die nicht vom selben Typ sind. Dies ist nicht ganz richtig, aber nehmen wir es erst einmal an. Wenn Sie nun wissen, dass die Variable immer nur auf Werte eines bestimmten Typs verweist, gibt es keinen Grund herauszufinden, ob ein Methodenaufruf zur Laufzeit gültig ist oder nicht, da Sie die Gültigkeit bestimmen können, bevor der Code jemals ausgeführt wird. Dies wird als Frühbindung bezeichnet.

Ein Beispiel zur Demonstration der späten Bindung in Rubin:

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

Die obige Abfolge von Aktionen ist in einer Sprache wie Java nicht möglich, in der alle Typen zur Laufzeit festgelegt sind.


1

Anstatt Ihnen eine akademische Definition zu geben, werde ich versuchen, Ihnen einige der Unterschiede anhand eines realen Beispiels mit VBA aufzuzeigen:

Frühes Binden:

Dim x As FileSystemObject
Set x = New FileSystemObject
Debug.Print x.GetSpecialFolder(0)

Dazu muss zur Entwurfszeit ein Verweis auf die Komponente "Microsoft Scripting Runtime" festgelegt werden . Dies hat den Vorteil, dass Sie bereits beim Kompilieren eine Fehlermeldung erhalten, wenn Sie einen Tippfehler FileSystemObjectoder einen Methodennamen wie haben GetSpecialFolder.

Späte Bindung

Dim x As Object
Set x = CreateObject("Scripting.FileSystemObject")
Debug.Print x.GetSpecialFolder(0)

Hierfür muss keine Referenz im Voraus festgelegt werden. Die Instanzerstellung und die Typbestimmung erfolgen nur zur Laufzeit. Der Compiler beschwert sich nicht zur Kompilierungszeit, wenn Sie versuchen, eine nicht vorhandene Methode von aufzurufen. xDies führt nur dann zu einem Laufzeitfehler, wenn die bestimmte Zeile ausgeführt wird.

Der Nachteil des späten Bindens ist also, dass Sie hier keine starke Typprüfung haben. Das ist aber auch der Vorteil - Nehmen wir an, Sie haben eine Komponente, in der mehrere Versionen vorhanden sind, und jede neuere Version bietet einige zusätzliche Funktionen. (Ein Beispiel aus der Praxis sind die MS Office-Komponenten wie die Excel-COM-Schnittstelle.) Durch die späte Bindung können Sie Code schreiben, der mit all diesen Versionen zusammenarbeitet. Sie können zuerst die spezifische Komponentenversion ermitteln und feststellen, ob Sie über diese verfügen Nur eine ältere Version verfügbar. Vermeiden Sie es, Funktionsaufrufe auszuführen, die mit dieser Version nicht funktionieren.


-2

Das wahrscheinlich häufigste Beispiel für eine späte Bindung ist das Auflösen von Internet-URLs. Es unterstützt dynamische Systeme und große Systeme, ohne dass versucht wird, jeden Standort auf der Welt zu verknüpfen und zu binden, bevor Sie einen erreichen können. Andererseits entsteht zur Laufzeit ein gewisser Overhead (DNS-Lookup, viel weniger IP-Routing).

Vor diesem Hintergrund sind die meisten Bindungsvarianten in Sprachumgebungen mehr oder weniger früh zur Kompilierungs- oder Verknüpfungszeit.

Jede Art hat Kosten und Nutzen.


Können Sie eine Referenz für diese Definition der Bindung erstellen? Ich habe nicht gehört, dass Internetadressen als "bindend" aufgelöst werden, obwohl das Binden das Auflösen von Namen ist. Ich nehme an, jemand hat argumentiert, dass das Konzept der frühen / späten Bindung auf das Auflösen von URIs auf Internetadressen angewendet werden kann. Dies ist jedoch keine gängige Interpretation, und das Konzept der frühen / späten Bindung geht der Zeit voraus, als Computer üblicherweise mit dem Internet verbunden waren.
Jay Elston
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.