Jaka jest różnica między wczesnym a późnym wiązaniem?

81

Jaka jest różnica między wczesnym a późnym wiązaniem?

James A. Rosen
źródło
4
Czy nie pomyliłbym się, mówiąc wczesne = bezpośrednie wywołanie funkcji, podczas gdy późne = wywołanie funkcji przez wskaźnik funkcji? Nigdy nie przestaje mnie zadziwiać, jak programiści potrafią przyjmować proste koncepcje i sprawiać, że wydają się o wiele bardziej złożone niż są (jako przejaw inteligencji?). Programowanie jest z natury bardzo łatwą dziedziną nauki, dopóki nie przejdziesz do rzeczy takich jak tworzenie typu float lub tworzenie kompilatorów.
Bob Blogge
Możliwy duplikat wczesnego i późnego wiązania
berkay

Odpowiedzi:

57

Krótka odpowiedź jest taka, że ​​wczesne (lub statyczne) wiązanie odnosi się do wiązania czasu kompilacji, a późne (lub dynamiczne) wiązanie odnosi się do wiązania środowiska uruchomieniowego (na przykład w przypadku używania odbicia).

Christian Hagelid
źródło
8
Jednak artykuł na Wikipedii dotyczący późnego wiązania ( en.wikipedia.org/wiki/Late_binding ) mówi, że „późne wiązanie jest często mylone z dynamiczną wysyłką, ale istnieją znaczące różnice”. Więc są takie same, czy nie? Jeśli są takie same, należy zmienić tę stronę Wikipedii.
Alexander Bird
2
Lepsza odpowiedź na stackoverflow tutaj stackoverflow.com/questions/484214/early-and-late-binding
Baggers
18

W językach kompilowanych różnica jest wyraźna.

Jawa:

//early binding:
public create_a_foo(*args) {
 return new Foo(args)
}
my_foo = create_a_foo();

//late binding:
public create_something(Class klass, *args) {
  klass.new_instance(args)
}
my_foo = create_something(Foo);

W pierwszym przykładzie kompilator może robić różne fajne rzeczy w czasie kompilacji. Po drugie, musisz mieć tylko nadzieję, że ktokolwiek używa tej metody, robi to odpowiedzialnie. (Oczywiście nowsze maszyny JVM obsługują tę Class<? extends Foo> klassstrukturę, co może znacznie zmniejszyć to ryzyko).

Kolejną korzyścią jest to, że IDE mogą łączyć się z definicją klasy, ponieważ jest zadeklarowana bezpośrednio w metodzie. Wywołanie create_something (Foo) może być bardzo dalekie od definicji metody, a jeśli patrzysz na definicję metody, fajnie byłoby zobaczyć implementację.

Główną zaletą późnego wiązania jest to, że ułatwia takie rzeczy, jak odwrócenie kontroli, a także niektóre inne zastosowania polimorfizmu i pisania kaczego (jeśli twój język obsługuje takie rzeczy).

James A. Rosen
źródło
6

Pobrano bezpośrednio z http://word.mvps.org/fAQs/InterDev/EarlyvsLateBinding.htm

Istnieją dwa sposoby wykorzystania automatyzacji (lub automatyzacji OLE) do programowego sterowania inną aplikacją.

Późne wiązanie wykorzystuje metodę CreateObject do tworzenia i wystąpienia obiektu aplikacji, którym można następnie sterować. Na przykład, aby utworzyć nowe wystąpienie programu Excel przy użyciu późnego wiązania:

 Dim oXL As Object
 Set oXL = CreateObject("Excel.Application")

Z drugiej strony, aby manipulować istniejącym wystąpieniem programu Excel (jeśli program Excel jest już otwarty), należy użyć GetObject (niezależnie od tego, czy używasz wczesnego czy późnego wiązania):

 Dim oXL As Object
 Set oXL = GetObject(, "Excel.Application")

Aby użyć wczesnego wiązania, musisz najpierw ustawić w projekcie odniesienie do aplikacji, którą chcesz manipulować. W edytorze VB dowolnej aplikacji pakietu Office lub w samym VB można to zrobić, wybierając Narzędzia + Referencje i wybierając żądaną aplikację z listy (np. „Biblioteka obiektów programu Microsoft Excel 8.0”).

Aby utworzyć nowe wystąpienie programu Excel przy użyciu wczesnego wiązania:

 Dim oXL As Excel.Application
 Set oXL = New Excel.Application

W obu przypadkach, nawiasem mówiąc, możesz najpierw spróbować pobrać istniejące wystąpienie programu Excel, a jeśli to zwróci błąd, możesz utworzyć nowe wystąpienie w programie obsługi błędów.

Ed S.
źródło
3
Wiem, że ta odpowiedź jest stara i pochodzi z innego źródła, ale nie jest dokładna. Późne wiązanie implikuje użycie CreateObject, ale CreateObject niekoniecznie oznacza późne wiązanie. Powiązanie nie dotyczy metody tworzenia wystąpienia obiektu, a jedynie sposobu jego zadeklarowania. Jeśli zadeklarujesz swój obiekt jako „As Excel.Application”, nie ma znaczenia, w jaki sposób go utworzysz. Zawsze używam CreateObject do tworzenia instancji odwołań do obiektów do bibliotek zewnętrznych, w ten sposób mogę przełączać się między wczesnym i późnym wiązaniem i muszę przełączać tylko jedną linię (nie dwie) - linię, która deklaruje obiekt.
JimmyPena
6

Podobna, ale bardziej szczegółowa odpowiedź z książki Herberta Schildta C ++: -

Wczesne wiązanie odnosi się do zdarzeń, które występują w czasie kompilacji. Zasadniczo wczesne wiązanie występuje, gdy wszystkie informacje potrzebne do wywołania funkcji są znane w czasie kompilacji. (Inaczej mówiąc, wczesne wiązanie oznacza, że ​​obiekt i wywołanie funkcji są wiązane podczas kompilacji). Przykłady wczesnego wiązania obejmują normalne wywołania funkcji (w tym standardowe funkcje biblioteczne), przeciążone wywołania funkcji i przeciążone operatory. Główną zaletą wczesnego wiązania jest wydajność. Ponieważ wszystkie informacje niezbędne do wywołania funkcji są określane w czasie kompilacji, tego typu wywołania funkcji są bardzo szybkie.

Przeciwieństwem wczesnego wiązania jest późne wiązanie. Późne wiązanie odnosi się do wywołań funkcji, które nie są rozwiązywane do czasu wykonania. Funkcje wirtualne służą do późnego wiązania. Jak wiesz, gdy dostęp odbywa się przez wskaźnik bazowy lub referencję, faktycznie wywoływana funkcja wirtualna jest określana przez typ obiektu wskazywanego przez wskaźnik. Ponieważ w większości przypadków nie można tego określić w czasie kompilacji, obiekt i funkcja są połączone dopiero w czasie wykonywania. Główną zaletą późnego wiązania jest elastyczność. W przeciwieństwie do wczesnego wiązania, późne wiązanie umożliwia tworzenie programów, które mogą reagować na zdarzenia występujące podczas wykonywania programu bez konieczności tworzenia dużej ilości „kodu awaryjnego”. Należy pamiętać, że ponieważ wywołanie funkcji nie jest rozwiązywane do czasu wykonania, późne wiązanie może spowodować nieco wolniejsze czasy wykonywania. Jednak dzisiaj

Pancuz Kumar
źródło
1
„obiekt i funkcja nie są połączone do czasu wykonania” Ta instrukcja wydaje się sugerować, że obiekt istnieje przed czasem wykonywania. Czy obiekty nie są wyłącznie jednostkami czasu wykonywania? Jest to klasa obiektu, który istnieje w czasie kompilacji. Można to lepiej wyrazić jako „wywołanie funkcji i jej implementacja nie są połączone do czasu wykonania”
programmerravi
jednym z przykładów późnego wiązania jest polimorfizm (w OOP), w którym używamy interfejsów lub klas abstrakcyjnych, a następnie łączymy się z nimi w czasie wykonywania.
Mohamad Mirzadeh
3

W językach tłumaczonych różnica jest nieco bardziej subtelna.

Rubin:

# early binding:
def create_a_foo(*args)
  Foo.new(*args)
end
my_foo = create_a_foo

# late binding:
def create_something(klass, *args)
  klass.new(*args)
end
my_foo = create_something(Foo)

Ponieważ Ruby nie jest (generalnie) skompilowany, nie ma kompilatora, który mógłby zrobić z góry fajne rzeczy. Rozwój JRuby oznacza, że ​​obecnie kompilowanych jest więcej Rubiego, dzięki czemu działa on bardziej jak Java, powyżej.

Problem z IDE nadal istnieje: platforma taka jak Eclipse może wyszukiwać definicje klas, jeśli je na stałe zakodujesz, ale nie może, jeśli pozostawisz je wywołującemu.

Odwrócenie kontroli nie jest zbyt popularne w Rubim, prawdopodobnie z powodu jego ekstremalnej elastyczności w czasie wykonywania, ale Railsy świetnie wykorzystują późne wiązanie, aby zmniejszyć ilość konfiguracji niezbędnej do uruchomienia aplikacji.

James A. Rosen
źródło
Ten punkt dotyczy również języków kompilowanych, które mogą zawierać komponenty skompilowane JIT i dołączone w czasie wykonywania w celu implementacji wtyczek lub struktur dynamicznych. Niektóre kanoniczne przykłady tego istnieją w Javie i oczywiście także w Rubim i Pythonie. Ekstremalnym przykładem jest Erlang, w którym środowisko uruchomieniowe może załadować dwie wersje dowolnego modułu jednocześnie w celu aktualizacji / obniżenia wersji na żywo. Więc chociaż większość kodu Erlang (większość?) Jest napisana jako czyste funkcje statycznie typowane, wymagania środowiska wykonawczego wymagają późnego wiązania i typów dynamicznych pod maską.
zxq9
0
public class child()
{    public void method1()
     {     System.out.println("child1");
     }
    public void method2()
     {     System.out.println("child2");
     }

}
public class teenager extends child()
{    public void method3()
     {      System.out.println("teenager3");
     }
}
public class adult extends teenager()
{     
    public void method1()
    {    System.out.println("adult1);
         super.method1();
     }
}


//In java
public static void main(String []args)
{    ((teenager)var).method1();
}

To zostanie wydrukowane

adult1
child1

We wczesnym wiązaniu kompilator będzie miał dostęp do wszystkich metod w podrzędnym i nastolatku, ale w późnym wiązaniu (w czasie wykonywania) będzie sprawdzać metody, które są przesłonięte w czasie wykonywania.

W związku z tym metoda method1 (from child - early binding) zostanie zastąpiona przez method1 from adult at runtime (late binding) Następnie zaimplementuje metodę method1 od child, ponieważ nie ma metody method1 w method1 u nastolatka.

Zauważ, że jeśli dziecko nie ma metody method1, kod w main nie zostałby skompilowany.

JBOND
źródło
0

Polimorfizm czasu kompilacji nazywany również przeciążeniem lub wczesnym wiązaniem lub wiązaniem statycznym, gdy mamy tę samą nazwę metody z różnymi zachowaniami. Dzięki wdrożeniu wielu prototypów tej samej metody i innego zachowania następuje w niej. Wczesne wiązanie odnosi się do pierwszej kompilacji programu. Ale w późnym powiązaniu obiekt jest runtime w programie. Nazywany także dynamicznym wiązaniem lub zastępowaniem lub polimorfizmem w czasie wykonywania.

Ghousepeer
źródło