У чому різниця між раннім та пізнім прив’язуванням?


82

У чому різниця між раннім та пізнім зв'язуванням?



4
Чи помилявся б я, сказавши ранній = прямий виклик функції, а пізній = виклик для функціонування через покажчик функції? Мене не перестає дивувати, як програмісти сприймають прості концепції та роблять їх більш складними, ніж вони є (як прояв інтелекту?). Програмування за своєю суттю є дуже легкою галуззю вивчення, поки ви не перейдете до таких речей, як те, як робиться тип плаваючого типу або розробка компіляторів.
Bob Blogge

Відповіді:


58

Коротка відповідь полягає в тому, що рання (або статична) прив'язка відноситься до прив'язки часу компіляції, а пізня (або динамічна) прив'язка відноситься до прив'язки до часу виконання (наприклад, коли ви використовуєте відображення).


8
Але стаття wikipedia про пізнє прив'язування ( en.wikipedia.org/wiki/Late_binding ) говорить, що "пізнє прив'язування часто плутають з динамічним відправленням, але є суттєві відмінності". То вони однакові чи ні? Якщо вони однакові, то цю сторінку wikipedia потрібно змінити.
Олександр Птах

2
Краще StackOverflow відповідь тут stackoverflow.com/questions/484214/early-and-late-binding
фасування

18

У компільованих мовах різниця сувора.

Java:

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

У першому прикладі компілятор може робити всілякі акуратні речі під час компіляції. По-друге, ви просто повинні сподіватися, що той, хто використовує метод, робить це відповідально. (Звичайно, новіші JVM підтримують Class<? extends Foo> klassструктуру, що може значно зменшити цей ризик.)

Ще одна перевага полягає в тому, що IDE можуть гаряче посилатись на визначення класу, оскільки це оголошено саме там у методі. Виклик create_something (Foo) може бути дуже далеким від визначення методу, і якщо ви дивитесь на визначення методу, може бути приємно побачити реалізацію.

Головною перевагою пізнього зв'язування є те, що це полегшує такі речі, як інверсія контролю, а також деякі інші способи поліморфізму та набору тексту для качок (якщо ваша мова підтримує такі речі).


6

Взято безпосередньо з http://word.mvps.org/fAQs/InterDev/EarlyvsLateBinding.htm

Існує два способи використання автоматизації (або OLE Automation) для програмного управління іншим додатком.

Пізнє прив'язування використовує CreateObject для створення та екземпляра об'єкта програми, яким ви потім можете керувати. Наприклад, щоб створити новий екземпляр Excel за допомогою пізнього прив'язки:

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

З іншого боку, для маніпулювання наявним екземпляром Excel (якщо Excel уже відкритий) ви б використовували GetObject (незалежно від того, використовуєте ви раннє чи пізнє прив'язування):

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

Щоб використовувати раннє прив’язування, спочатку потрібно встановити посилання у своєму проекті на програму, якою ви хочете маніпулювати. У редакторі VB будь-якої програми Office або в самій VB ви робите це, вибравши Інструменти + Посилання та вибравши потрібну програму зі списку (наприклад, «Бібліотека об’єктів Microsoft Excel 8.0»).

Щоб створити новий екземпляр Excel за допомогою раннього прив'язки:

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

У будь-якому випадку, до речі, спочатку ви можете спробувати отримати існуючий екземпляр Excel, і якщо це поверне помилку, ви можете створити новий екземпляр у своєму обробнику помилок.


3
Я знаю, що ця відповідь давня і надійшла звідкись ще, але не є точною. Пізнє прив'язування передбачає використання CreateObject, але CreateObject не обов'язково передбачає пізнє прив'язування. Прив'язка не застосовується до методу створення екземпляра об'єкта, лише до того, як він оголошений. Якщо ви оголосите свій об'єкт "Як Excel.Application", не має значення, як ви його створили. Я завжди використовую CreateObject для створення екземплярів посилань на об'єкти до зовнішніх бібліотек, таким чином я можу перемикатися між раннім і пізнім прив'язуванням і маю переключити лише один рядок (а не два) - рядок, який оголошує об'єкт.
JimmyPena

6

Подібна, але більш детальна відповідь з книги Герберта Шильдта C ++: -

Рання прив'язка відноситься до подій, що відбуваються під час компіляції. По суті, раннє зв'язування відбувається, коли вся інформація, необхідна для виклику функції, відома під час компіляції. (Інакше кажучи, раннє прив'язування означає, що об'єкт і виклик функції пов'язані під час компіляції.) Приклади раннього прив'язки включають звичайні виклики функцій (включаючи стандартні функції бібліотеки), перевантажені виклики функцій та перевантажені оператори. Головною перевагою раннього зв'язування є ефективність. Оскільки вся інформація, необхідна для виклику функції, визначається під час компіляції, ці типи викликів функцій дуже швидкі.

Протилежністю ранньому зв'язуванню є пізнє зв'язування. Пізнє прив'язування відноситься до викликів функцій, які не вирішуються до часу виконання. Віртуальні функції використовуються для досягнення пізнього прив'язки. Як відомо, коли доступ здійснюється через базовий вказівник або посилання, фактично викликана віртуальна функція визначається типом об'єкта, на який вказує вказівник. Оскільки в більшості випадків це неможливо визначити під час компіляції, об’єкт та функція не пов’язані до часу виконання. Головна перевага пізнього зв’язування - гнучкість. На відміну від раннього прив'язки, пізнє прив'язування дозволяє створювати програми, які можуть реагувати на події, що відбуваються під час виконання програми, не створюючи великої кількості "коду на випадок непередбаченості". Майте на увазі, що оскільки виклик функції не вирішується до часу виконання, пізнє прив'язування може призвести до дещо повільнішого часу виконання. Однак сьогодні,


1
"об'єкт і функція не пов'язані до часу виконання" Це твердження, мабуть, означає, що об'єкт існує до часу виконання. Хіба об'єкти не є суто об'єктами часу виконання? Це клас об'єкта, який існує під час компіляції. Це можна краще сказати як "виклик функції та її реалізація не пов'язані до часу виконання"
programmerravi

одним із прикладів пізнього прив'язки є поліморфізм (в ООП), який ми використовуємо інтерфейси або абстрактні класи, а потім прив'язуємо до нього під час виконання.
Мохамад Мірзаде

3

У інтерпретованих мовах різниця є дещо більш тонкою.

Рубін:

# 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)

Оскільки Ruby (як правило) не компілюється, немає компілятора, який міг би виконати чудові попередні матеріали. Зростання JRuby означає, що в наш час збирається більше Ruby, однак це робить його більш схожим на Java вище.

Проблема з IDE все ще стоїть: така платформа, як Eclipse, може шукати визначення класів, якщо ви їх жорстко кодуєте, але не може, якщо ви залишаєте їх для абонента.

Інверсія управління не дуже популярна в Ruby, можливо, через надзвичайну гнучкість виконання, але Rails широко використовує пізнє прив'язування, щоб зменшити кількість конфігурації, необхідної для запуску вашого додатка.


Цей пункт стосується також скомпільованих мов, які можуть включати компоненти, скомпільовані JIT і включені під час виконання для реалізації плагінів або динамічних фреймворків. Деякі канонічні приклади цього існують на Java, і, звичайно, Ruby та Python також. Надзвичайним прикладом є Erlang, де середовище виконання може завантажувати дві версії будь-якого модуля одночасно для оновлення / оновлення в реальному часі. Отже, хоча багато коду Erlang (більшість?) Написано як статично набрані чисті функції, вимоги до виконання вимагають пізнього прив'язки та динамічних типів під капотом.
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();
}

Це роздрукує

adult1
child1

При ранньому прив'язуванні компілятор матиме доступ до всіх методів у дитини та підлітка, але при пізньому прив'язуванні (під час виконання) він перевірить наявність методів, замінених під час виконання.

Отже, метод1 (від дочірнього - раннє прив'язування) буде замінено методом1 від дорослого під час виконання (пізнє прив'язка). Тоді він буде реалізовувати метод1 від дочірнього, оскільки в методі1 у підлітка немає методу1.

Зверніть увагу, що якби дочірній матеріал не мав методу1, тоді основний код не компілювався.


0

Поліморфізм часу компіляції також називається перевантаженням або ранньою прив'язкою або статичним прив'язуванням, коли ми маємо одне і те ж ім'я методу з різною поведінкою. Реалізуючи кілька прототипів одного і того ж методу та різної поведінки, що відбувається в ньому. Рання прив'язка стосується першої компіляції програми. Але в кінці прив'язки об'єкта час виконання відбувається в програмі. Також називається динамічним прив'язуванням або перевизначенням або поліморфізмом виконання.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.