В чем разница раннего и позднего связывания
Перейти к содержимому

В чем разница раннего и позднего связывания

  • автор:

В чем разница раннего и позднего связывания

Видео: Раннее и Позднее Связывание

Содержание

Ключевое отличие — ранний против позднего связывания

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

Такие языки программирования, как Java, поддерживают объектно-ориентированное программирование (ООП). Это парадигма, которая позволяет создавать программу или программное обеспечение с использованием объектов. В программе есть несколько объектов. Эти объекты связаны друг с другом и передают сообщения с помощью методов. У каждого объекта есть характеристики и поведение. Характеристики описываются свойствами или атрибутами. Поведение описывается с помощью методов. У объекта Student могут быть такие характеристики, как имя, возраст и они представлены свойствами. Объект Student может иметь такое поведение, как изучение и чтение, и они представлены методами. Одним из основных столпов ООП является полиморфизм. Это позволяет объекту вести себя по-разному. Раннее связывание и позднее связывание — это две концепции полиморфизма. Методы перегрузки связаны с использованием раннего связывания. Переопределенные методы связываются с использованием позднего связывания.

1. Обзор и основные отличия
2. Что такое раннее связывание
3. Что такое поздняя привязка
4. Сходство между ранним и поздним связыванием
5. Параллельное сравнение — раннее и позднее связывание в табличной форме
6. Резюме

Что такое раннее связывание?

В раннем связывании информация о классе используется для разрешения вызова метода. Раннее связывание происходит во время компиляции. Это также известно как статическая привязка. В этом процессе привязка происходит до фактического запуска программы. Методы перегрузки связаны с использованием раннего связывания. Обратитесь к программе ниже.

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

Что такое позднее связывание?

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

Согласно приведенной выше программе, класс Shape имеет метод рисования. Классы Circle и класс Triangle расширяют класс Shape. Следовательно, эти два класса могут наследовать атрибуты и методы класса Shape. Класс формы — это базовый класс. Классы Circle и Triangle являются производными классами. Класс Circle и класс Triangle также имеют метод рисования со своими собственными реализациями. Таким образом, метод рисования в классе Shape переопределяется методами рисования производных классов.

В основной программе создается ссылочная переменная s типа Shape. Во время компиляции компилятор будет ссылаться только на метод рисования базового класса. Во время выполнения будут выполняться разные методы рисования. Сначала s будет указывать на объект типа Shape. Итак, вызывается метод рисования класса Shape. Затем s будет указывать на объект типа Circle, и он вызовет метод рисования класса Circle. Наконец, s укажет на объект типа Triangle и вызовет метод рисования в классе Triangle. Методы вызываются в зависимости от объектов. Следовательно, объект используется для разрешения вызова метода в Позднем связывании. Информация, необходимая для привязки, предоставляется во время выполнения, поэтому скорость выполнения ниже по сравнению с ранним связыванием.

В чем сходство между ранним и поздним связыванием?

  • И раннее связывание, и позднее связывание связаны с полиморфизмом, который является столпом ООП.

В чем разница между ранним и поздним связыванием?

Раннее связывание против позднего связывания

Резюме — рано против позднего связывания

ООП обычно используется для разработки программного обеспечения. Один из основных столпов ООП — полиморфизм. С этим связаны раннее и позднее связывание. Раннее связывание происходит во время компиляции, а позднее — во время выполнения. При перегрузке метода связывание происходит с использованием раннего связывания. При переопределении метода связывание происходит с использованием позднего связывания. Разница между ранним и поздним связыванием заключается в том, что раннее связывание использует информацию о классе для разрешения вызова метода, в то время как позднее связывание использует объект для разрешения вызова метода.

Разница между ранним и поздним связыванием в Java

В этом посте будет обсуждаться разница между ранним и поздним связыванием (статическим и динамическим связыванием) в Java.

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

В Java есть два типа связывания — раннее (или статическое) связывание и позднее (или динамическое) связывание. В этом посте представлен обзор различий между ними.

  1. The рано привязка происходит во время компиляции и поздно привязка происходит во время выполнения.
  2. При раннем связывании определение метода и вызов метода связываются во время компиляции. Это происходит, когда вся информация, необходимая для вызова метода, доступна во время компиляции.

Пример раннего и позднего связывания в Java

результат:

Car Started
Vehicle Stopped

Рассмотрим приведенный выше код. Он имеет два класса – Vehicle класс и Car класс, где Car расширяет Vehicle учебный класс. Каждый класс имеет два метода – start() а также stop() . stop() метод является статическим, в то время как start() метод нестатичен. Теперь, когда мы вызываем start() а также stop() методы, использующие ссылку на родительский класс, start() вызывается метод дочернего класса, а stop() вызывается метод родительского класса.

Это потому что stop() является статическим методом и, следовательно, не может быть переопределен. Таким образом, привязка stop() происходит во время самой компиляции (раннее связывание). С другой стороны, start() — это нестатический метод, переопределенный в дочернем классе. Таким образом, информация о типе объекта доступна только во время выполнения (позднее связывание), а значит, start() метод Car класс называется.

C#. Позднее и раннее связывание. Полиморфизм. Основные понятия. Примеры. Передача в метод ссылки на базовый класс

Позднее и раннее связывание. Полиморфизм. Основные понятия. Примеры. Передача в метод ссылки на базовый класс. Ключевые слова virtual , override , new

Данная тема есть продолжением темы:

Содержание

Поиск на других ресурсах:

1. Понятие позднего и раннего связывания. Ключевые слова virtual , override

При изучении темы полиморфизма важно понять понятие позднего и раннего связывания, которое используется компилятором при построении кода программы в случае наследования.

Если классы образовывают иерархию наследования, то при обращении к элементам класса, компилятор может реализовывать один из двух возможных способов связывания кода:

  1. Раннее связывание – связанное с формированием кода на этапе компиляции. При раннем связывании, программный код формируется на основе известной информации о типе (класс) ссылки. Как правило, это ссылка на базовый класс в иерархии классов.
  2. Позднее связывание – связанное с формированием кода на этапе выполнения. Если в иерархии классов встречается цепочка виртуальных методов (с помощью слов virtual, override), то компилятор строит так называемое позднее связывание. При позднем связывании вызов метода происходит на основании типа объекта, а не типа ссылки на базовый класс. Позднее связывание используется, если нужно реализовать полиморфизм.

Выбор того или иного вида связывания для каждого отдельного элемента (метода, свойства, индексатора и т.п.) определяется компилятором по следующим правилам:

  • если в иерархии унаследованных классов объявляется невиртуальный элемент, то реализуется раннее связывание;
  • если в иерархии унаследованных классов объявляется виртуальный элемент, то выполняется позднее связывание (рисунки 1, 2). Виртуальный элемент в базовом классе обозначается ключевым словом virtual, во всех унаследованных классах ключевым словом override. В C# виртуальным элементом может быть метод, событие, индексатор или свойство.

Необходимые условия для реализации позднего связывания:

  • классы должны образовывать иерархию наследования;
  • в классах должны быть методы с одинаковой сигнатурой. Элементы (методы) производных классов должны перекрывать (override) соответствующие элементы (методы) базовых классов;
  • элементы (методы) класса должны быть виртуальными, то есть должны быть обозначены ключевыми словами virtual, override.

На рисунке 1 приведен пример, который отображает отличие между поздним и ранним связыванием на примере двух классов A , B в которых реализован метод Print() .

C#. Наследование. Позднее и раннее связывание. Отличия

Рисунок 1. Позднее и раннее связывание. Отличия

В случае раннего связывания, как только компилятор встречает строку

происходит объявление ссылки ref , которая имеет тип базового класса A . Дальнейшее присваивание

связывает ссылку с объектом objB , однако тип ссылки устанавливается A . Поэтому вызов

вызовет метод Print() класса A .

В случае позднего связывания, сначала на основе описания классов A , B компилятор определяет, что метод Print() есть виртуальным. Для виртуального метода компилятор строит таблицу виртуальных методов Print() , которая содержит смещение адресов каждого виртуального метода для каждого класса иерархии (это отдельная тема для исследования).

формируется связывание ссылки ref с типом A . После присваивания

компилятор присваивает ссылке ref адрес экземпляра objB и определяет тип связывания как тип B (поскольку метод Print() виртуальный). За основу берется тип объекта. В результате ссылка ref связывается с методом Print() , который реализован в классе B (а не в классе A ) – выполняется так называемое «позднее связывание».

Как следствие, после вызова

будет вызван метод Print() класса B.

На рисунке 2 приведено отличие между поздним и ранним связываниями на примере трех классов A, B , C , в каждом из которых объявлен метод Print() .

C#. Наследование. Раннее и позднее связывание для метода на примере трех классов

Рисунок 2. Раннее и позднее связывание для метода Print() на примере трех классов A , B , C

Вызов метода Print() по ссылке на объект класса C

2. Что такое полиморфизм? Динамический полиморфизм

Полиморфизм – это свойство программного кода изменяться в зависимости от ситуации, которая возникает в момент выполнения программы.

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

Использование преимуществ полиморфизма возможно в ситуациях:

  • когда классы образовывают иерархию с помощью концепции наследования;
  • когда в классах, которые образовывают иерархию, есть элементы (методы, свойства и т.п.) с одинаковой сигнатурой. В таких случаях возникает понятие «переопределение метода» (method override).

В языке программирования C# полиморфизм обеспечивается с помощью ключевых слов virtual и override . Благодаря использованию этих ключевых слов обеспечивается динамический полиморфизм. Термин «динамический» означает, что вызов виртуального элемента осуществляется динамично во время выполнения программы в зависимости от типа объекта, для которого этот элемент вызывается.

3. Для каких элементов класса можно применять полиморфизм?

Полиморфизм можно применять для следующих элементов:

  • методов;
  • свойств;
  • индексаторов;
  • событий.
4. Схематическое объяснение полиморфизма

На рисунке 3 демонстрируется применение полиморфизма на примере двух классов.

C#. Реализация полиморфизма на примере двух классов A, B

Рисунок 3. Реализация полиморфизма на примере двух классов A , B

5. Полиморфизм в случае передачи в метод ссылки на базовый класс. Позднее связывание

В любой метод может быть передана ссылка на базовый класс. С помощью этой ссылки также можно вызвать методы, свойства которые поддерживают полиморфизм.

Пример.

Заданы 2 класса с именами Base и Derived . Класс Derived наследует класс Base . В обоих классах определен виртуальный метод Info() , который выводит информацию о классе. Вызов виртуального метода Info() осуществляется из статического метода ShowInfo() класса Program . Метод ShowInfo() получает входным параметром ссылку на базовый класс и по этой ссылке обращается к методу Info() класса. В зависимости от того, экземпляр какого класса передается в метод ShowInfo() , соответствующий метод Info() вызывается.

6. Какие требования накладываются на элемент класса для того, чтобы он поддерживал полиморфизм?

Для того, чтобы элемент класса (например метод) поддерживал полиморфизм, его нужно сделать виртуальным. Чтобы элемент класса был виртуальным, нужно выполнить следующие требования:

  • в базовом классе этот элемент (метод, свойство) должен быть обозначен как virtual или abstract. Ключевое слово abstract также делает элемент виртуальным. Это слово используется, если элемент класса есть абстрактным. Более подробно об абстрактных классах описывается здесь ;
  • в производных классах одноименные элементы должны быть обозначены как override . Если в производном классе нужно реализовать невиртуальный метод, имя которого совпадает с виртуальным методом базового класса, то этот метод обозначается ключевым словом new (смотрите пункт 7).
7. Использование ключевого слова new в цепочке виртуальных методов. Пример

Как известно, элемент класса, который объявлен виртуальным ( virtual ), передает возможность реализовать полиморфизм в одноименных элементах унаследованных классов. Таким образом, виртуальные элементы образовывают цепочку вниз по иерархии.

Для того, чтобы элемент класса, который переопределяет ( override ) виртуальный элемент базового класса, не поддерживал полиморфизм нужно указать ключевое слово new . Если в цепочке одноименных виртуальных методов встречается один невиртуальный метод (с ключевым словом new ) то этот метод разрывает цепочку.

Пример. Заданы классы с именами A1 , A2 , A3 , A4 . Классы образовывают иерархию наследования. В классе A3 объявляется метод Print() с ключевым словом new , разрывающий цепочку виртуальных методов.

Текст демонстрационной программы следующий

На рисунке 4 схематично изображен вызов метода Print() в случае использования ключевого слова new.

C#. Наследование. Виртуальные методы. Разрыв цепи виртуальных методов

Рисунок 4. Иерархия классов A1 , A2 , A3 , A4 . Разрыв цепи виртуальных методов Print() в классе A3

Результат работы программы

8. Пример классов Figure -> Rectangle -> RectangleColor , демонстрирующих полиморфизм

Объявить класс Figure , содержащий поле name , которое определяет название фигуры. В классе Figure объявить следующие методы:

  • конструктор с 1 параметром;
  • метод Display() , отображающий название фигуры.

Из класса Figure унаследовать класс Rectangle (прямоугольник), который содержит следующие поля:

  • координату левого верхнего угла (x1; y1);
  • координату правого нижнего угла (x2; y2).

В классе Rectangle реализовать следующие методы и функции:

  • конструктор с 5 параметрами, который вызывает конструктор базового класса Figure ;
  • конструктор без параметров, который реализует установку координат углов (0; 0), (1; 1) и вызывает конструктор с 5 параметрами с помощью средства this ;
  • метод Display() , отображающий название фигуры и значения внутренних полей. Данный метод обращается к одноименному методу базового класса;
  • метод Area() , возвращающий площадь прямоугольника.

Из класса Rectangle унаследовать класс RectangleColor . В классе RectangleColor реализовать поле color (цвет) и следующие методы;

18.5 – Раннее и позднее связывание

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

Когда программа на C++ выполняется, она выполняется последовательно, начиная с начала main() . Когда встречается вызов функции, точка выполнения переходит к началу вызываемой функции. Как CPU узнает об этом?

Когда программа компилируется, компилятор преобразует каждую инструкцию в вашей программе на C++ в одну или несколько строк машинного кода. Каждой строке машинного кода дается собственный уникальный адрес в последовательности адресов. То же самое и с функциями – когда встречается функция, она преобразуется в машинный код и получает следующий доступный адрес. Таким образом, каждая функция получает уникальный адрес.

Связывание относится к процессу, который используется для преобразования идентификаторов (например, имен переменных и функций) в адреса. Хотя связывание используется как для переменных, так и для функций, в этом уроке мы сосредоточимся на связывании функций.

Раннее связывание

Большинство вызовов функций, с которыми сталкивается компилятор, будут прямыми вызовами функций. Прямой вызов функции – это инструкция, которая вызывает функцию напрямую. Например:

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

Давайте посмотрим на простую программу калькулятора, в которой используется раннее связывание:

Поскольку add() , subtract() и multiply() являются прямыми вызовами функций, компилятор будет использовать раннее связывание для разрешения вызовов функций add() , subtract() и multiply() . Компилятор заменит вызов функции add() инструкцией, которая сообщает процессору перейти к адресу функции add() . То же самое верно и для subtract() и multiply() .

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

В некоторых программах до момента выполнения (когда программа запущена) невозможно узнать, какая функция будет вызвана. Это называется поздним связыванием (или динамическим связыванием). В C++ один из способов получить позднее связывание – использовать указатели на функции. Вкратце, указатель на функцию – это тип указателя, который указывает на функцию, а не на переменную. Функция, на которую указывает указатель, может быть вызвана с помощью применения оператора вызова функции ( () ) к указателю.

Например, следующий код вызывает функцию add() :

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

В этом примере вместо прямого вызова функции add() , subtract() или multiply() мы установили pFcn так, чтобы он указывал на функцию, которую мы хотим вызвать. Затем мы вызываем функцию через этот указатель. Компилятор не может использовать раннее связывание для разрешения вызова функции pFcn(x, y) , потому что во время компиляции он не может сказать, на какую функцию будет указывать pFcn !

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

В следующем уроке мы рассмотрим, как позднее связывание используется для реализации виртуальных функций.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *