В языках программирования привязка имен — это ассоциация сущностей (данных и/или кода) с идентификаторами . [1] Говорят, что идентификатор, привязанный к объекту , ссылается на этот объект. В машинных языках нет встроенного понятия идентификаторов, но привязка имени к объекту как услуга и нотация для программиста реализуются языками программирования. Привязка тесно связана с областью видимости , поскольку область видимости определяет, какие имена привязываются к каким объектам – в каких местах программного кода ( лексически ) и в каком из возможных путей выполнения ( временно ).
Использование идентификатора id в контексте, который устанавливает привязку для id , называется вхождением привязки (или определения). Во всех других случаях (например, в выражениях , присваиваниях и вызовах подпрограмм ) идентификатор обозначает то, с чем он связан; такие явления называются прикладными явлениями.
Примером статической привязки является прямой вызов функции C : функция, на которую ссылается идентификатор, не может изменяться во время выполнения.
Примером динамической привязки является динамическая диспетчеризация , например вызов виртуального метода C++ . Поскольку конкретный тип полиморфного объекта неизвестен до времени выполнения (как правило), выполняемая функция динамически привязывается. Возьмем, к примеру, следующий Java- код:
public void foo ( java.util . List <String> list ) { list . _ _ _ _ добавить ( «бар» ); }
List
является интерфейсом , поэтому list
должен относиться к его подтипу . list
может ссылаться на LinkedList
, an ArrayList
или какой-либо другой подтипList
. Метод, на который ссылается, add
неизвестен до времени выполнения. В C, где нет динамической привязки, аналогичная цель может быть достигнута путем вызова функции, на которую указывает переменная или выражение типа указателя на функцию , значение которого неизвестно, пока оно не будет оценено во время выполнения.
Повторное связывание не следует путать с мутацией или присвоением.
Рассмотрим следующий код Java :
LinkedList <String> список ; _ _ список = новый LinkedList <String> ( ) ; список . добавить ( «фу» ); список = ноль ; { LinkedList < Целое число > list = новый LinkedList < Целое число > (); список . добавить ( Целое число ( 2 )); }
Идентификатор list
привязан к переменной в первой строке; во втором — переменной присваивается ссылка на объект (связанный список строк). Затем связанный список, на который ссылается переменная, мутируется, добавляя в список строку. Далее переменной присваивается константа null
. В последней строке идентификатор перепривязывается к области действия блока. Операции внутри блока обращаются к новой переменной, а не к переменной, ранее привязанной к list
.
Поздняя статическая привязка — это вариант привязки, промежуточный между статической и динамической привязкой. Рассмотрим следующий пример PHP :
класс A { public static $word = "привет" ; public static function hello () { print self :: $word ; } }класс B расширяет A { public static $word = "пока" ; }Б :: здравствуйте ();
В этом примере интерпретатор PHP связывает ключевое слово self
внутри A::hello()
с классом A
, и поэтому вызов B::hello()
создает строку «привет». Если бы семантика self::$word
была основана на позднем статическом связывании, то результатом было бы «пока».
Начиная с версии PHP 5.3 поддерживается позднее статическое связывание. [3] В частности, если бы self::$word
приведенное выше было изменено на static::$word
, как показано в следующем блоке, где ключевое слово static
будет привязано только во время выполнения, то результатом вызова B::hello()
будет «пока»:
класс A { public static $word = "привет" ; public static function hello () { print static :: $word ; } }класс B расширяет A { public static $word = "пока" ; }Б :: здравствуйте ();