Лекция
Привет, сегодня поговорим про позднее связывание, обещаю рассказать все что знаю. Для того чтобы лучше понимать что такое позднее связывание, раннее связывание , настоятельно рекомендую прочитать все из категории Выполнение скриптов на стороне клиента JavaScript, jqvery, JS фреймворки (Frontend).
позднее связывание , динамическое связывание [1] или динамическое связывание [2] - это механизм компьютерного программирования, в котором метод, вызываемый для объекта, или функция, вызываемая с аргументами, ищется по имени во время выполнения .
При раннем связывании или статическом связывании в объектно-ориентированном языке на этапе компиляции исправляются все типы переменных и выражений. Обычно это сохраняется в скомпилированной программе как смещение в таблице виртуальных методов («v-table»). [3] В отличие от этого, при позднем связывании компилятор не считывает достаточно информации для проверки существования метода или привязки своего слота к v-таблице. Вместо этого метод ищется по имени во время выполнения.
Основное преимущество использования позднего связывания в программировании модели компонентных объектов (COM) состоит в том, что компилятору не требуется ссылаться на библиотеки, содержащие объект, во время компиляции . Это делает процесс компиляции более устойчивым к конфликтам версий, при которых v-таблица класса может быть случайно изменена. (Это не является проблемой для платформ, скомпилированных с своевременной компиляцией, таких как .NET или Java, потому что v-таблица создается во время выполнения виртуальной машиной для библиотек по мере их загрузки в работающее приложение.
Термин «позднее связывание» восходит как минимум к 1960-м годам, где его можно найти в Сообщениях ACM . Этот термин широко использовался для описания соглашений о вызовах в таких языках, как Lisp, хотя обычно имел отрицательный оттенок производительности. [5]
В 1980-х годах Smalltalk популяризировал объектно-ориентированное программирование (ООП) и, как следствие, позднее связывание. Алан Кей однажды сказал: «ООП для меня означает только обмен сообщениями, локальное сохранение, а также защиту и сокрытие состояния-процесса и крайнее позднее связывание всех вещей. Это можно сделать в Smalltalk и в LISP. Возможно, есть и другие системы в что это возможно, но я о них не знаю ". [6]
В начале и середине 1990-х годов Microsoft активно продвигала свой стандарт COM как двоичный интерфейс между различными языками программирования ООП. COM-программирование в равной степени способствовало раннему и позднему связыванию, при этом многие языки поддерживают и то, и другое на уровне синтаксиса.
В 2000 году Алекс Мартелли ввел термин « утиная печать » для обозначения аналогичной концепции, но с другим акцентом. В то время как позднее связывание обычно фокусируется на деталях реализации, утиная типизация фокусируется на способности игнорировать типы и концентрироваться на методах, которые в настоящее время имеет объект.
В большинстве языков с динамической типизацией список методов объекта может быть изменен во время выполнения. Это требует позднего связывания.
раннее связывание - это когда метод, который будет вызван, известен во время компиляции, например, вызов статического метода.
Раннее связывание, как было отмечено выше, происходит на этапе компиляции. Оно применяется при вызове обычных методов (не виртуальных).
dynamic dispatch - это когда имеется ссылочная переменная, и в зависимости от того экземпляр какого класса будет создан, и будет вызван соответствующий метод..
Позднее связывание - это когда вызов метода может быть осуществлен только во время выполнения и у компилятора нет информации, чтобы проверить корректность такого вызова. Об этом говорит сайт https://intellect.icu . В java это можно сделать при помощи рефлексии.
Позднее связывание напротив происходит во время выполнения. Выполняется оно при вызове виртуальных функций класса-потомка для определения того, какой именно метод следует вызывать.
Раннее и Позднее связывание в других языках программирования
Исходя из того, что раннее связывание выполняется на этапе компиляции, а позднее - в рантайме, первый вариант обладает лучшим быстродействием, однако второй необходим для реализации полиморфизма.
По поводу Java могу сказать, что там, если не ошибаюсь, ко всем методам по умолчанию применяется позднее связывание (если они не помечены модификатором final) в отличие от, скажем, С++, где по умолчанию применяется раннее связывание. Е
Обычный метод bind называется «ранним связыванием», поскольку фиксирует привязку сразу же.
Как только значения привязаны — они уже не могут быть изменены. В том числе, если метод объекта, который привязали, кто-то переопределит — «привязанная» функция этого не заметит.
Позднее связывание — более гибкое, оно позволяет переопределить привязанный метод когда угодно.
Например, попытаемся переопределить метод при раннем связывании:
…Привязка все еще работает со старым методом, несмотря на то что он был переопределен.
При позднем связывании bind вызовет не ту функцию, которая была в sayHi на момент привязки, а ту, которая есть на момент вызова.**
Встроенного метода для этого нет, поэтому нужно реализовать.
Синтаксис будет таков:
obj Объект
method Название метода (строка)
Код:
Этот вызов похож на обычный bind, один из вариантов которого как раз и выглядит какbind(obj, "method"), но работает по-другому.
Поиск метода в объекте: context[funcName], осуществляется при вызове, самой оберткой.
Поэтому, если метод переопределили — будет использован всегда последний вариант.
В частности, пример, рассмотренный выше, станет работать правильно:
Позднее связывание позволяет привязать к объекту даже метод, которого еще нет!
Конечно, предполагается, что к моменту вызова он уже будет определен
Например:
В некотором смысле, позднее связывание всегда лучше, чем раннее. Оно удобнее и надежнее, так как всегда вызывает нужный метод, который в объекте сейчас.
Но оно влечет и небольшие накладные расходы — поиск метода при каждом вызове.
Когда я эхо с помощью
echo my_dog::get_name();
Я возьму "stacey".
Если я изменюсь
возвращает static::$name
к
возврат self::$name;
ответ сводится к "paulie".
В JavaScript у меня есть следующие конструкторы объектов
Когда я вызываю свой метод с помощью
предупреждение(my_pet_instance.get_name());
Я всегда буду получать "stacey".
Для моделирования статических переменных можно присоединять свойства непосредственно к конструкторам:
Однако для достижения того, что вы ищете, вы можете использовать цепочку прототипов вместо этого:
Позднее связывание ищет функцию в объекте в момент вызова.
Оно используется для привязки в тех случаях, когда метод может быть переопределен после привязки или на момент привязки не существует.
Обертка для позднего связывания (без карринга):
call вызывает функцию с заданным контекстом, а bind, по своей сути есть обертка, привязывающая контекст, которую можно передать в функцию.
call - позднее связывание, bind - раннее связывание.
Такое динамическое позднее связывание обычно медленнее (требует больше циклов процессора), чем связывание во время компиляции [11].как и в случае большинства процессов, выполняемых во время выполнения. Однако динамическое связывание часто более эффективно использует пространство (на диске и в памяти во время выполнения). Когда библиотека связана статически, каждый запускаемый процесс связан со своей собственной копией вызываемых библиотечных функций. Следовательно, если библиотека вызывается много раз разными программами, одни и те же функции в этой библиотеке дублируются в нескольких местах системной памяти. Использование общих динамических библиотек означает, что вместо связывания каждого файла с его собственной копией библиотеки во время компиляции и потенциально бесполезной траты памяти, только одна копия библиотеки всегда сохраняется в памяти за раз, освобождая пространство памяти для используется в другом месте. [12] Кроме того, при динамической компоновке библиотека загружается только в том случае, если она действительно используется.
Позднее связывание имеет худшую производительность, чем вызов метода раннего связывания. В большинстве реализаций правильный адрес метода необходимо искать по имени при каждом вызове, что требует относительно дорогостоящего поиска по словарю и, возможно, логики разрешения перегрузки, но на современных компьютерах это обычно незначительно.
Для некоторых компиляторов позднее связывание может помешать использованию проверки статического типа. При выполнении вызова с поздним связыванием компилятор должен предположить, что метод существует. Это означает, что простая орфографическая ошибка может вызвать ошибку времени выполнения. Точное исключение зависит от языка, но обычно оно называется как-то вроде «Метод не найден» или «Метод отсутствует». Современные компиляторы избегают этого, гарантируя, что каждый возможный вызов должен иметь реализацию во время компиляции.
Позднее связывание может помешать формам статического анализа, необходимого для интегрированной среды разработки (IDE). Например, функция IDE «перейти к определению» может не работать при вызове с поздним связыванием, если у IDE нет способа узнать, к какому классу может относиться вызов. Современная среда IDE легко решает эту проблему, особенно для объектно-ориентированных языков, поскольку метод с поздним связыванием всегда указывает интерфейс или базовый класс, к которому ведет «перейти к определению», а «найти все ссылки» можно использовать для поиска всех реализаций или отменяет.
Аналогичная проблема заключается в том, что возможное отсутствие типизированной информации может помешать созданию графов зависимостей. Однако другие методы программирования, такие как абстрактные интерфейсы, могут привести к тем же проблемам. Современная среда IDE может создавать такие графы зависимостей так же легко, как и «найти все ссылки».
К сожалению, в одной статье не просто дать все знания про позднее связывание. Но я - старался. Если ты проявишь интерес к раскрытию подробностей,я обязательно напишу продолжение! Надеюсь, что теперь ты понял что такое позднее связывание, раннее связывание и для чего все это нужно, а если не понял, или есть замечания, то не стесняйся, пиши или спрашивай в комментариях, с удовольствием отвечу. Для того чтобы глубже понять настоятельно рекомендую изучить всю информацию из категории Выполнение скриптов на стороне клиента JavaScript, jqvery, JS фреймворки (Frontend)
Комментарии
Оставить комментарий
Выполнение скриптов на стороне клиента JavaScript, jqvery, JS фреймворки (Frontend)
Термины: Выполнение скриптов на стороне клиента JavaScript, jqvery, JS фреймворки (Frontend)