Поздняя привязка - Late binding


Поздняя привязка, динамическое связывание,[1] или же динамическая связь[2]- хотя процесс не идентичен динамическое связывание библиотеки импортированного кода - это механизм компьютерного программирования, в котором метод, вызываемый для объекта, или функция, вызываемая с аргументами, ищется по имени в время выполнения. Другими словами, имя связывается с конкретной операцией или объектом во время выполнения, а не во время компиляции.

С раннее связывание, или же статическая привязка, в объектно-ориентированный язык, этап компиляции исправляет все типы переменных и выражений. Обычно это сохраняется в скомпилированной программе как смещение в таблица виртуальных методов ("v-таблица").[3] Напротив, с поздним связыванием компилятор не считывает достаточно информации, чтобы проверить, существует ли метод, или привязать свой слот к v-таблице. Вместо этого метод ищется по имени во время выполнения.

Основное преимущество использования позднего связывания в Компонентная объектная модель (COM) программирование заключается в том, что компилятору не требуется ссылаться на библиотеки, содержащие объект в время компиляции. Это делает процесс компиляции более устойчивым к конфликтам версий, при которых v-таблица класса может быть случайно изменена. (Это не проблема своевременная компиляция -компилированные платформы, такие как .NET или Java, потому что v-таблица создается во время выполнения виртуальная машина против библиотек по мере их загрузки в работающее приложение.[4])

История

Термин «позднее связывание» восходит как минимум к 1960-м годам, где его можно найти в Коммуникации ACM. Этот термин широко использовался для описания соглашений о вызовах в таких языках, как Lisp, хотя обычно имел отрицательный оттенок производительности.[5]

В 80-е годы Болтовня популяризировал объектно-ориентированного программирования (ООП) и с ним поздняя привязка. Алан Кей однажды сказал: «ООП для меня означает только обмен сообщениями, локальное сохранение, защиту и сокрытие состояния-процесса, а также крайнее позднее связывание всех вещей. Это можно сделать в Smalltalk и в LISP. Возможно, существуют другие системы, в которых это возможно, но я о них не знаю ".[6]

В начале и середине 1990-х годов Microsoft активно продвигала свой стандарт COM как двоичный интерфейс между различными языками программирования ООП. COM-программирование в равной степени способствовало раннему и позднему связыванию, при этом многие языки поддерживают оба на уровне синтаксиса.

В 2000 г. Алекс Мартелли ввел термин "утка печатать "для обозначения аналогичной концепции, но с другим акцентом. В то время как позднее связывание обычно фокусируется на деталях реализации, утиная типизация фокусируется на способности игнорировать типы и концентрироваться на методах, которые в настоящее время имеет объект.

Поздние реализации привязки

Позднее связывание в объектно-ориентированных языках с динамической типизацией

В большинстве динамически типизированный языках список методов объекта может быть изменен во время выполнения. Это требует позднего связывания.

Позднее связывание в Лиспе

В Лисп. вызовы глобальных функций с поздним связыванием эффективно просматриваются во время выполнения через символ функциональная ячейка. Эти привязки функций изменяемы.

Пример использования интерактивного Закрытие Common Lisp сессия:

? (defun фу ()    (бар число Пи))   ; вызывается еще не определенная функция BAR; Предупреждения компилятора:; В FOO: неопределенная функция BARFOO? (defun бар (Икс)   ; теперь мы определяем это    (* Икс 2))БАР? (фу)    ; вызывает foo и использует недавнее определение BAR6.283185307179586D0? (defun бар (Икс)   ; теперь мы переопределяем BAR    (* Икс 1000))БАР? (фу)    ; FOO теперь вызывает новую функцию, нет необходимости перекомпилировать / связывать / загружать FOO3141.592653589793D0? (тип 'бар)   ; BAR - это символСИМВОЛ? (символ-функция 'бар)  ; символ BAR имеет привязку к функции#<Скомпилированная функция БАР # x302000D1B21F>

Позднее связывание в C ++

В C ++ поздняя привязка (также называемая «динамической привязкой») относится к тому, что обычно происходит, когда виртуальный ключевое слово используется в объявлении метода. Затем C ++ создает так называемую виртуальную таблицу, которая является таблицей поиска таких функций, к которым всегда будут обращаться при их вызове.[7] Обычно термин «позднее связывание» используется вместо «динамическая отправка ".

Позднее связывание в языках COM

В программировании COM вызов метода с поздним связыванием выполняется с использованием IDispatch интерфейс. Некоторые языки на основе COM, такие как Visual Basic 6, имеют синтаксическую поддержку для вызова этого интерфейса.[8] Это делается путем определения типа переменной как Object. Другие, такие как C ++, требуют, чтобы вы явно вызывали GetIDsOfNames для поиска метода и Invoke для его вызова.

Позднее связывание в .NET

В .NET под поздним связыванием понимается переопределение виртуальный метод, такой как C ++, или реализация интерфейса. Компилятор создает виртуальные таблицы для каждого вызова виртуального метода или метода интерфейса, который используется во время выполнения для определения реализации, которую необходимо выполнить.

Так же, как COM и Java, Common Language Runtime предоставляет API-интерфейсы отражения, которые могут выполнять вызовы позднего связывания. Использование этих вызовов зависит от языка.

В C # 4 язык также добавил «динамический» псевдотип. Это будет использоваться вместо типа объекта, чтобы указать, что желательна поздняя привязка. Конкретный необходимый механизм позднего связывания определяется во время выполнения с использованием среды выполнения динамического языка в качестве отправной точки.

Visual Basic использует их во всех случаях, когда переменная имеет тип Object и действует директива компилятора Option Strict Off. Это настройка по умолчанию для нового проекта VB. До версии 9 только объекты .NET и COM могли связываться с опозданием. В VB 10 это было расширено до объектов на основе DLR.

Поздняя привязка в Java

В Java есть три определения позднего связывания.

Ранние документы по Java обсуждали, как классы не были связаны между собой во время компиляции. В то время как типы статически проверяются во время компиляции, различные реализации классов могут быть заменены незадолго до времени выполнения, просто перезаписав файл класса. Пока новое определение класса имело те же имена классов и методов, код все еще работал. В этом смысле оно похоже на традиционное определение позднего связывания.

В настоящее время в программировании на Java популярно использовать термин позднее связывание как синоним динамическая отправка. В частности, это относится к Java разовая отправка механизм, используемый с виртуальными методами.

Наконец, Java может использовать позднее связывание, используя свои API отражения и тип самоанализ примерно так же, как это делается в программировании на COM и .NET. Вообще говоря, те, кто программирует только на Java, не называют эту позднюю привязку. Точно так же использование методов «утиной печати» не одобряется в программировании на Java, вместо этого используются абстрактные интерфейсы.

Oracle, нынешний владелец Java, известен тем, что использовал термин позднее связывание в смысле «утиной печати» при обсуждении как Java, так и других языков в одной и той же документации.[9]

Раннее и позднее связывание в PL / SQL и Ada

При использовании раннего связывания между Ada и хранимой в базе данных процедурой проверяется метка времени, чтобы убедиться, что хранимая процедура не изменился с момента компиляции кода. Это позволяет ускорить выполнение и предотвращает запуск приложения с неправильной версией хранимой процедуры.[10]

При использовании позднего связывания проверка отметки времени не выполняется, а хранимая процедура выполняется через анонимный блок PL / SQL. Хотя это может быть медленнее, оно устраняет необходимость перекомпилировать все клиентские приложения при изменении хранимой процедуры.

Это различие является уникальным для PL / SQL и Ada. Другие языки, которые могут вызывать процедуры PL / SQL, а также другие механизмы баз данных, используют только позднее связывание.

Критика

Позднее связывание имеет худшую производительность, чем вызов метода раннего связывания. В большинстве реализаций правильный адрес метода необходимо искать по имени при каждом вызове, что требует относительно дорогостоящего поиска по словарю и, возможно, логики разрешения перегрузки, но на современных компьютерах это обычно незначительно.

Для некоторых компиляторов позднее связывание может препятствовать использованию проверки статического типа. При выполнении вызова с поздним связыванием компилятор должен предположить, что метод существует. Это означает, что простая орфографическая ошибка может вызвать ошибку времени выполнения. Точное исключение зависит от языка, но обычно оно называется как-то вроде «Метод не найден» или «Метод отсутствует». Современные компиляторы избегают этого, гарантируя, что каждый возможный вызов должен иметь реализацию во время компиляции.

Позднее связывание может предотвратить формы статический анализ нужен интегрированная среда развития (IDE). Например, функция IDE «перейти к определению» может не работать при вызове с поздним связыванием, если у IDE нет способа узнать, к какому классу может относиться вызов. Современная среда IDE легко решает эту проблему, особенно для объектно-ориентированных языков, поскольку метод с поздним связыванием всегда указывает интерфейс или базовый класс, к которому ведет «перейти к определению», а «найти все ссылки» можно использовать для поиска всех реализаций или отменяет.

Аналогичная проблема заключается в том, что возможное отсутствие типизированной информации может помешать созданию графов зависимостей. Однако другие методы программирования, такие как абстрактные интерфейсы, могут привести к тем же проблемам. Современная среда IDE может создавать такие графы зависимостей так же легко, как и «найти все ссылки».

Смотрите также

Рекомендации

  1. ^ Буч, Гради. Объектно-ориентированный анализ и дизайн. Addison-Wesley, 1994. стр. 71.
  2. ^ Шрайнер, Аксель-Тобиас (1994). Объектно-ориентированное программирование с использованием ANSI-C (PDF). Мюнхен: Хансер. п. 15. ISBN  3-446-17426-5.
  3. ^ «Использование раннего и позднего связывания в автоматизации». Microsoft. 2003-09-06. Получено 2014-06-27.
  4. ^ «Структура виртуальной машины Java: динамическое связывание». Sun Microsystems. 1999. с. 3.6.3. Получено 2013-09-21.
  5. ^ Методы программной инженерии, Дж. Н. Бакстон, Брайан Рэнделл, Научный комитет НАТО, Научный комитет НАТО, 1970 г.
  6. ^ "Доктор Алан Кей о значении" объектно-ориентированного программирования """. Purl.org. Получено 2013-08-16.
  7. ^ «12.5 - Виртуальный стол« Learn C ». Learncpp.com. 2008-02-08. Получено 2013-08-16.
  8. ^ «Использование раннего и позднего связывания в автоматизации». Support.microsoft.com. Получено 2011-01-15.
  9. ^ «Вызов сервера WebLogic из клиентского приложения COM». Download.oracle.com. Получено 2013-08-16.
  10. ^ «Раннее и позднее связывание, модуль Oracle SQL * для руководства программиста на Ada». Download.oracle.com. Получено 2011-01-15.