Elettracompany.com

Компьютерный справочник
2 просмотров
Рейтинг статьи
1 звезда2 звезды3 звезды4 звезды5 звезд
Загрузка...

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

Java: механизмы наследования, ссылочные типы данных, интерфейсы, вложенные классы

Механизмы наследования

Класс — это шаблон , в котором определяются данные и поведение объекта. Объекты одного класса совместно используют общую структуру данных и общее поведение.

Объявление класса в языке Java создает новый ссылочный тип , определяющий как описание методов, так и их реализацию.

Объявление интерфейса создает новый ссылочный тип , который специфицирует описание методов и имена некоторых констант, но не определяет саму их реализацию.

Интерфейс может быть объявлен для расширения одного или нескольких интерфейсов.

Наследование позволяет определять новые классы в терминах существующих классов.

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

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

Язык Java разрешает несколько уровней наследования, определяемых непосредственным суперклассом и косвенными суперклассами . Наследование можно использовать для создания иерархии классов.

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

  • расширение суперкласса путем добавления новых данных и методов;
  • замена методов суперкласса путем их переопределения;
  • слияние методов из суперклассов вызовом одноименных методов из соответствующих суперклассов.

Объявление класса

Объявление класса вводит новый ссылочный тип и определяет или часть, или всю его реализацию.

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

Объявление класса может иметь следующее формальное описание:

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

Вложенный класс описывается так же, как и внешний.

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

Класс может иметь более одного модификатора класса.

В языке программирования Java существуют следующие модификаторы класса:

  • abstract , являющийся модификатором реализации класса и определяющий, что класс может иметь абстрактные методы (методы, не имеющие реализации);
  • final , являющийся модификатором ограничения иерархии классов и указывающий, что класс не может иметь подклассов (не должен никогда появляться во фразе extends объявления класса). Класс с модификатором final обязан реализовать все свои интерфейсы.
  • public является модификатором доступа и указывает, что к данному классу разрешен доступ из других пакетов. Доступ может быть выполнен или непосредственно указанием квалифицированного имени класса, или с использованием оператора import .

Для указания модификаторов класса применяются следующие правила:

  • если класс, имеющий абстрактные методы , объявлен без модификатора abstract , то возникает ошибка компиляции;
  • для абстрактных классов нельзя создавать экземпляры класса;
  • если при объявлении класса не указан модификатор public , то класс доступен только внутри своего пакета;
  • при компиляции каждый общедоступный класс всегда записывается в отдельный файл с расширением .CLASS . Такой файл называется модулем компиляции;
  • имя общедоступного класса должно совпадать с именем файла, содержащего код класса на языке Java;
  • один модуль компиляции может содержать только один класс или интерфейс, имеющие модификатор public ;
  • один модуль компиляции может одновременно содержать объявление общедоступного класса и нескольких интерфейсов или классов, не имеющих модификатора public ;
  • один модуль компиляции не может одновременно содержать объявление общедоступного класса ( public class ) и общедоступного интерфейса ( public interface );
  • объявление класса одновременно с модификаторами final и abstract вызывает ошибку компиляции.

Любой класс может иметь только один суперкласс , указываемый ключевым словом extends . Наследуемый суперкласс должен быть доступным классом и не иметь модификатора final .

По умолчанию предполагается, что в том случае, если для класса не указано никакого суперкласса , то его непосредственным суперклассом станет класс Object из пакета java.lang , который всегда является корневым классом в любой формируемой иерархии классов.

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

Раннее и позднее связывание является одним из проявлений полиморфизма, позволяя выполнять одним оператором вызов различных методов в зависимости от типа объекта.

Pro Java

Страницы

6 июл. 2015 г.

Полиморфизм – позднее связывание.

В первой статье по полиморфизму мы кратко познакомились с тем что это такое. По существу это просто переопределение методов суперкласса в подклассах. Но наверное вся мощь и красота этого еще не совсем понятна. И может не совсем ясно для чего все это нужно. Теперь попробуем разобраться более глубже. Приготовились к глубокой медитации. Оммммм…. Ну и погнали! 🙂

Возьмем затертый до дыр пример с фигурами. Не будем отклонятся от классиков жанра 🙂

И так общим суперклассом у нас будет класс Shape, и у него будут наследники царь, царевич, король, королевич, Circle, Square, Triangle. Но мы пойдем чуть дальше заезженного примера 🙂 и образуем еще парочку наследников. Oval у нас будет наследником Circle, а Rect наследником Square.

На диаграмме все можно изобразить примерно так:

Методы drow() в каждом классе будут переопределены, а метод erase() будет просто наследоваться от Shape. Теперь осталось всю эту красоту забабахать в коде 🙂

Код у нас вышел очень красивый 🙂 Буквочка к буквочке 🙂 и вывод у него такой же 🙂

Теперь внимательно посмотрим на код. У нас есть одномерный массив shape классов Shape размером 6. И первому элементу массива мы присвоили ссылку на объект Shape (созадется new Shape()). А вот далее начинается магия, которую вы уже видели и должны понимать. Это называется восходящее преобразование. Я уже про это говорил, что ссылка суперкласса может указывать на объекты подклассов. И так далее мы присваиваем следующим элементам массива shape ссылки на подклассы. Но затем в выводе работает вообще сумасшедшая магия полиморфизма – вызываются методы подклассов, хотя ссылка имеет тип суперкласса.

Теперь вопрос от куда компилятор знает метод какого объекта должен быть вызван?

А компилятор то и не знает… 🙂 Ну а кто же тогда знает?

Кто, кто? Дракон в пальто!

Хотя в приведенной программе это не очень очевидно, что компилятор не знает, так как мы присваиваем элементам массива ссылки на конкретные объекты.

Но я это сделал для простоты понимания и наглядности того что происходит.

Чтобы все было по честному и было видно кто компилятор точно не может знать на какой объект будут ссылаться элементы массива, эту программу можно модифицировать так, чтобы массив заполнялся случайным образом.

Слева как раз и приведен пример измененного отрывка этой же программы, но массив уже заполняется случайным образом, что видно из вывода программы:

Встает все тот же вопрос – кто знает метод какого объекта надо вызывать в каждом конкретном случае? А знает это JVM. Но как она узнает? И тут начинается серьезная магия виртуальной машины Java вкупе с компилятором Java.

Читать еще:  Эта переменная не определена mathcad ошибка

Сам компилятор не знает, но может подсказать JVM как надо обрабатывать инструкции вызова методов.

Чтобы в полной мере разобраться в сути про­исходящего, необходимо рассмотреть понятие связывания (binding).

Присоединение вызова метода к телу метода называется связыванием . Если связывание проводится перед запуском программы (компилятором и компоновщиком, если он есть), оно называется ранним связыванием (early binding). В процедурных языках никакого выбора связывания не было. Компиляторы C поддерживают только один тип вызова — раннее связывание.

Проблема определения метод какого объекта вызывать в нашей программе решается благодаря позднему связыванию (late binding), то есть связыванию, проводимому во время выполнения программы, в зависимости от типа объекта. Позднее связывание также называют динамическим (dynamic binding) или связыванием на стадии выполнения (runtime binding).

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

В прошлом посте, мы уже вкратце коснулись этого вопроса. Теперь постараемся понять более глубоко.

Для всех методов Java используется механизм позднего связывания, если только метод не был объявлен как private . Вызов private метода компилируется в инструкцию байт-кода invokespecial, которая вызывает реализацию метода из конкретного класса, определенного в момент компиляции. Вызов метода с другим уровнем доступа компилируется в invokevirtual, которая уже смотрит на тип объекта по ссылке в момент исполнения. Финальные неприватные методы тоже вызываются через invokevirtual.

В инструкцию байт-кода invokespesial компилируются:

  • Инициализационный вызов ( ) при создании объекта
  • Вызов private метода
  • Вызов метода с использованием ключевого слова super

Есть конечно еще несколько других инструкций байт-кода для вызова методов: invokedynamic, invokeinterface и invokestatic. Но хотя об их использовании и говорят их названия, пока мы их обсуждать не будем. Если кому-то сильно хочется то можно почитать эту статью на враждебном каждому правоверному программисту буржуйском языке 🙂 Чтиво полезное, но для понимания того о чём сейчас речь, достаточно того, что я тут уже написал. Так же можно почитать эту статью на родном языке.

И так, надо уже переходить к практике. Модифицируем программу из этого поста, следующим образом:

Я подсветил private и final модификаторы чтобы вы обратили на них внимание и затем на то, какой байт-код для них создаст компилятор. Вывод у нашей программы сейчас следующий:

Заострю внимание на том, что ссылка root имеет тип Root, но указывает на объект типа Branch. И как я уже не однократно писал, обычные методы вызываются по версии объекта на который указывает ссылка. Именно через это свойство и реализуется полиморфизм.

Но в нашем случае, не смотря на это, первая команда вывела на консоль Root, а не Branch.

Теперь заглянем под капот этой программе при помощи команды: javap -c -p -v Root.class

Эта команда сгенерирует достаточно длинный вывод, но нам нужна только эта часть:

Как видно из вывода команда root.prt() была преобразована в вызов типа invokespecial, а команда branch.prt() в invokevirtual.

Вот мы и раскрыли магию всего этого действа. Надеюсь вам понравилось представление 🙂 и теперь вы стали чуть больше понимать как работают полиморфные методы в Java.

Философского пеликана гнездо

воскресенье, 8 июня 2014 г.

Полиморфизм в Java. Динамическое и статическое связывание. Инициализация объектов. Поведение полиморфных методов при вызове из конструкторов.

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

В языке Java объектные переменные являются полиморфными (polymorphic). Например:

Переменная типа King может ссылаться как на объект типа King, так и на объект любого подкласса King.

Возьмем следующий пример:

Что происходит, когда вызывается метод, принадлежащий объекту king ?

1. Компилятор проверяет объявленный тип объекта и имя метода, нумерует все методы с именем speech в классе AerusTargarien и все открытые методы speech в суперклассах AerusTargarien . Теперь компилятору известны возможные кандидаты при вызове метода.

2. Компилятор определяет типы передаваемых в метод аргументов. Если найден единственный метод, сигнатура которого совпадает с аргументами, происходит вызов. Этот процесс называется разрешением перегрузки (overloading resolution) . Т.е. при вызове king.speech(«Homo homini lupus est») компилятор выберет метод speech(String quotation) , а не speech() .

Если компилятор находит несколько методов с подходящими параметрами (или ни одного), выдается сообщение об ошибке.

Теперь компилятор знает имя и типы параметров метода,подлежащего вызову.

3. В случае, если вызываемый метод является private , static , final или конструктором, используется статическое связывание (early binding). В остальных случаях метод, подлежащий вызову, определяется по фактическому типу объекта, через который происходит вызов. Т.е. во время выполнения программы используется динамическое связывание (late binding).

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

Таблица методов для класса King выглядит так:

  • speech() — King . speech()
  • speech(String quotation) — King . speech( String quotation )
  • speech(Boolean speakLoudly) — King . speech( Boolean speakLoudly )

А для класса AerysTargaryen — так:

  • speech() — AerysTargaryen . speech()
  • speech(String quotation) — AerysTargaryen . speech( String quotation )
  • speech(Boolean speakLoudly) — King. speech( Boolean speakLoudly )

Методы, унаследованные от Object, в данном примере игнорируются.

При вызове king. speech() :

  1. Определяется фактический тип переменной king . В данном случае это AerysTargaryen .
  2. Виртуальная машина определяет класс, к которому принадлежит метод speech()
  3. Происходит вызов метода.

Связывание всех методов в Java осуществляется полиморфно, через позднее связывание. Динамическое связывание обладает одной важной особенностью: оно позволяет модифицировать программы без перекомпиляции их кодов. Это делает программы динамически расширяемыми (extensible).

А что произойдет, если вызвать в конструкторе динамически связываемый метод конструируемого объекта? Например:

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

Это значит, что при вызове конструктора new AerysTargaryen() будут вызваны:

  1. new Object()
  2. new King()
  3. new AerysTargaryen()

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

  1. Память, выделенная под новый объект, заполняется двоичными нулями.
  2. Конструкторы базовых классов вызываются в описанном ранее порядке. В этот момент вызывается переопределенный метод speech() (да, перед вызовом конструктора класса AerysTargaryen ), где обнаруживается, что переменная victimName равна null из-за первого этапа.
  3. Вызываются инициализаторы членов класса в порядке их определения.
  4. Исполняется тело конструктора производного класса.
Читать еще:  Long parselong java

В частности из-за таких поведенческих моментов стоит придерживаться следующего правила написания конструкторов:
— выполняйте в конструкторе лишь самые необходимые и простые действия по инициализации объекта
— по возможности избегайте вызова методов, не определенных как private или final (что в данном контексте одно и то же).

Читать онлайн «Философия java» автора Эккель Брюс — RuLit — Страница 52

Разве не лучше было бы написать единственный метод, в аргументе которо­го передается базовый класс, а не один из производных классов? Разве не удоб­нее было бы забыть о производных классах и написать обобщенный код для ба­зового класса?

Именно это и позволяет делать полиморфизм. Однако большинство про­граммистов с опытом работы на процедурных языках при работе с полимор­физмом испытывают некоторые затруднения.

Сложности с программой Music.java обнаруживаются после ее запуска. Она вы­водит строку Wind.play(). Именно это и требуется, но не понятно, откуда берется такой результат. Взгляните на метод tune():

public static void tune(Instrument i) <

Метод получает ссылку на объект Instrument. Как компилятор узнает, что ссылка на Instrument в данном случае указывает на объект Wind, а не на Brass или Stringed? Компилятор и не знает. Чтобы в полной мере разобраться в сути про­исходящего, необходимо рассмотреть понятие связывания (binding).

Присоединение вызова метода к телу метода называется связыванием. Если связывание проводится перед запуском программы (компилятором и компонов­щиком, если он есть), оно называется ранним связыванием (early binding). Возмож­но, ранее вам не приходилось слышать этот термин, потому что в процедурных языках никакого выбора связывания не было. Компиляторы С поддерживают только один тип вызова — раннее связывание.

Неоднозначность предыдущей программы кроется именно в раннем связы­вании: компилятор не может знать, какой метод нужно вызывать, когда у него есть только ссылка на объект Instrument

Проблема решается благодаря позднему связыванию (late binding), то есть связыванию, проводимому во время выполнения программы, в зависимости от типа объекта. Позднее связывание также называют динамическим (dynamic) или связыванием на стадии выполнения (runtime binding). В языках, реализую­щих позднее связывание, должен существовать механизм определения факти­ческого типа объекта во время работы программы, для вызова подходящего ме­тода. Иначе говоря, компилятор не знает тип объекта, но механизм вызова методов определяет его и вызывает соответствующее тело метода. Механизм позднего связывания зависит от конкретного языка, но нетрудно предполо­жить, что для его реализации в объекты должна включаться какая-то дополни­тельная информация.

Для всех методов Java используется механизм позднего связывания, если только метод не был объявлен как final (приватные методы являются final по умолчанию). Следовательно, вам не придется принимать решений относитель­но использования позднего связывания — оно осуществляется автоматически.

Зачем объявлять метод как final? Как уже было замечено в предыдущей гла­ве, это запрещает переопределение соответствующего метода. Что еще важнее, это фактически «отключает» позднее связывание или, скорее, указывает компи­лятору на то, что позднее связывание не является необходимым. Поэтому для методов final компилятор генерирует чуть более эффективный код. Впрочем, в большинстве случаев влияние на производительность вашей программы незна­чительно, поэтому final лучше использовать в качестве продуманного элемента своего проекта, а не как средство улучшения производительности.

Теперь, когда вы знаете, что связывание всех методов в Java осуществляется полиморфно, через позднее связывание, вы можете писать код для базового класса, не сомневаясь в том, что для всех производных классов он также будет работать верно. Другими словами, вы «посылаете сообщение объекту и позво­ляете ему решить, что следует делать дальше».

Классическим примером полиморфизма в ООП является пример с геомет­рическими фигурами. Он часто используется благодаря своей наглядности, но, к сожалению, некоторые новички начинают думать, что ООП подразумева­ет графическое программирование — а это, конечно же, неверно.

В примере с фигурами имеется базовый класс с именем Shape (фигура) и различные производные типы: Circle (окружность), Square (прямоугольник), Triangle (треугольник) и т. п. Выражения типа «окружность есть фигура» оче­видны и не представляют трудностей для понимания. Взаимосвязи показаны на следующей диаграмме наследования:

Восходящее преобразование имеет место даже в такой простой команде: Shape s = new CircleO;

Здесь создается объект Circle, и полученная ссылка немедленно присваивает­ся типу Shape. На первый взгляд это может показаться ошибкой (присвоение одного типа другому), но в действительности все правильно, потому что тип Circle (окружность) является типом Shape (фигура) посредством наследования. Компилятор принимает команду и не выдает сообщения об ошибке.

Предположим, вызывается один из методов базового класса (из тех, что были переопределены в производных классах):

Опять можно подумать, что вызывается метод draw() из класса Shape, раз имеется ссылка на объект Shape — как компилятор может сделать что-то дру­гое? И все же будет вызван правильный метод Circle.draw(), так как в программе используется позднее связывание (полиморфизм).

Следующий пример показывает несколько другой подход:

//: polymorph!sm/shape/Shapes java package polymorphism.shape;

public class Shape <

public void drawO <> public void eraseO <> > Hi­ll’. polymorphism/shape/Circle java package polymorphism shape: import static net.mindview.util.Print.*,

public class Circle extends Shape <

public void drawO < printC'Circle.drawO"); >public void eraseO < printC'Circle.eraseO"). >> Hi­ll-. polymorphism/shape/Square.java package polymorphism.shape: import static net.mindview.util Print *.

public class Square extends Shape <

продолжение &

import static net mindview.util Print.*;

public class Triangle extends Shape <

public void drawO < printC'Triangle.drawO"). >public void eraseO < printC'Triangle eraseO"). >> Hi­ll. polymorphism/shape/RandomShapeGenerator java II «Фабрика», случайным образом создающая объекты package polymorphism.shape; import java.util *;

public class RandomShapeGenerator <

private Random rand = new Random(47); public Shape next О <

case 0: return new CircleO; case 1: return new SquareO, case 2: return new TriangleO;

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

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

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

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

содержание

история

Термин «позднее связывание» восходит , по крайней мере , в 1960 — е года, где он может быть найден в связи с АКМ . Термин был широко используется для описания соглашения о вызовах в таких языках , как Lisp, хотя обычно с отрицательными коннотациями о производительности.

Читать еще:  Stringbuilder append java

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

С C # 4, язык также добавили «динамический» псевдо-типа. Это можно было бы использовать вместо типа объекта, чтобы указать, что позднее связывание желательно. Конкретный позднее связывание механизм должен определяется во время выполнения с помощью Dynamic Language Runtime в качестве отправной точки.

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 и других языках в той же документации.

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

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

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

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

критика

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

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

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

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

Ссылка на основную публикацию
Adblock
detector