Модераторы: LSD, AntonSaburov

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Позднее связывание 
V
    Опции темы
Sherst
Дата 21.3.2006, 20:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 131
Регистрация: 26.10.2005

Репутация: нет
Всего: 2



Привет всем!

Прочитал в одной книжке:
"Для решения проблемы объектно-ориентированные языки используют концепцию позднего связывания. Когда вы посылаете объекту сообщение, код, который будет вызван, не определяется, пока не начнется время выполнения. Компилятор не убеждается, что функция существует, а выполняет проверку типа аргумента и возвращаемого значения, но он не знает точный код для выполнения."

Это что получается я могу послать объекту сообщение(метод), который нигде не определен?

Код

class A 
{
}

class B extends A 
{
 public static void main(String[] args) {
   A a = new A();
   a.myMethod();//myMethod()-нигде не определен
 }
}


PM MAIL   Вверх
powerOn
Дата 21.3.2006, 20:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


software saboteur
****


Профиль
Группа: Участник
Сообщений: 4367
Регистрация: 7.10.2005

Репутация: 47
Всего: 159



Цитата

Это что получается я могу послать объекту сообщение(метод), который нигде не определен?


Нет. Тут немного другое имеется ввиду.
Скажу сразу: позднее связывание это механизм вызова виртуального метода, заключается он в том, что адрес (а не имя smile ) метода, который необходимо выполнить будет изветсен только во время выполнения программы. Каждый класс обладающий виртуальными методами имеет так назаваемую таблицу виртуальных функций, в которой храняться их адреса. Во время содания/выполнения класса в эту таблицу вносятся реальные адреса функций и именно по этим адресам происходит их вызов.

Это имеет отношение только к виртуальным функциям, которыми в Java все и являются по умолчанию в отличии от С++. Не виртуальная функция в С++ вызывается по смещению относительно начала класса, а виртуальные как и в Java по указателю из таблицы виртуальных функций.

Это все хорошо проявляется при наследовании классов и при переопределении методов.

Вот пример
Код

class A {
 public void meth() {
 System.out.println("a meth call!");
}
}

class B extends A {
 public void meth(){
 System.out.println("b meth call!");
}
}


class C {
 public static void main(String [] s) {
     A  a1 = new A();
     B  b1 = new B(); 
     a1.meth(); // a meth call!
     b1.meth(); // b meth call!
     
     A a2 = new B();
     a2.meth(); // b meth call!           Не будь этот метод виртуальным на экране бы появилось - a meth call!

 }

}









--------------------
user posted image нет времени думать - нужно писать КОД!

PM MAIL   Вверх
Sherst
Дата 21.3.2006, 21:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 131
Регистрация: 26.10.2005

Репутация: нет
Всего: 2



Т.е. выходит что на этапе выполнения программы (не компиляции) для класса создается
таблица виртуальных ф-ий ?
А могу ли я как-то программно просмотреть содержимое таблицы виртуальных функций?
И еще вопрос smile получается что в Java не существует не виртуальных ф-ий?

Заранее спасибо.
PM MAIL   Вверх
powerOn
Дата 21.3.2006, 21:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


software saboteur
****


Профиль
Группа: Участник
Сообщений: 4367
Регистрация: 7.10.2005

Репутация: 47
Всего: 159



Цитата

И еще вопрос smile получается что в Java не существует не виртуальных ф-ий?


Существуют - static функции. Поменяй добавь этот идентификатор к функциям в примере и почувствуй разницу.

Цитата

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


Нет на этапе компиляции. Все функции по умолчанию виртуальны, кроме статических.

Цитата

А могу ли я как-то программно просмотреть содержимое таблицы виртуальных функций?


Точно не знаю, посмотри в сторону Java Reflections, там есть возможность получить исчерпывающую информацию об объектах.





--------------------
user posted image нет времени думать - нужно писать КОД!

PM MAIL   Вверх
LSD
Дата 21.3.2006, 21:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Leprechaun Software Developer
****


Профиль
Группа: Модератор
Сообщений: 15718
Регистрация: 24.3.2004
Где: Dublin

Репутация: 210
Всего: 538



Цитата(MoonCat @ 21.3.2006, 21:16 Найти цитируемый пост)
Нет на этапе компиляции.

Нет, на этапе выполнения smile
Пока класс не загружен в таблице его не будет, так что таблицы динамические.

Цитата(Sherst @ 21.3.2006, 21:11 Найти цитируемый пост)
А могу ли я как-то программно просмотреть содержимое таблицы виртуальных функций?

Средствами Java никак, возможно в JNI есть методы, но сильно сомеваюсь. Т.к. эта штука очень сильно влияет на производительность и наверняка подвержена частым изменениям.

Цитата(Sherst @ 21.3.2006, 21:11 Найти цитируемый пост)
И еще вопрос  получается что в Java не существует не виртуальных ф-ий?

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


--------------------
Disclaimer: this post contains explicit depictions of personal opinion. So, if it sounds sarcastic, don't take it seriously. If it sounds dangerous, do not try this at home or at all. And if it offends you, just don't read it.
PM MAIL WWW   Вверх
powerOn
Дата 21.3.2006, 21:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


software saboteur
****


Профиль
Группа: Участник
Сообщений: 4367
Регистрация: 7.10.2005

Репутация: 47
Всего: 159



Цитата

Нет, на этапе выполнения smile
Пока класс не загружен в таблице его не будет, так что таблицы динамические.



Етественно пока класса в памяти нет, ни о какой таблице вирт.ф. говорить не стоит. Эта таблица появится только вместе с загруженным классом.
Но размер таблицы виртуальных функций неизменен для определенного и зависит от количества виртуальных функции. Точнее размер вт = кол-ву виртуальных. функции. (Естественно с учетом наследования т.е. вирт. ф. предков тоже считаютя). И изменить его можно только добавив/удалив вирт.ф-цию. - Что во время выполнения невозможно.


Я скорее воспринял этот вопрос как о размере таблицы, и скорее всего не много ни так.... smile
Добавлено @ 21:42
Цитата

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


функции final естественно не виртуальны, поскольку их нельзя переопределить. А виртуальность функции безсмысленна без переопределения.


--------------------
user posted image нет времени думать - нужно писать КОД!

PM MAIL   Вверх
LSD
Дата 21.3.2006, 21:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Leprechaun Software Developer
****


Профиль
Группа: Модератор
Сообщений: 15718
Регистрация: 24.3.2004
Где: Dublin

Репутация: 210
Всего: 538



Цитата(MoonCat @ 21.3.2006, 21:40 Найти цитируемый пост)
Етественно пока класса в памяти нет, ни о какой таблице вирт.ф. говорить не стоит. Эта таблица появится только вместе с загруженным классом.
Но размер таблицы виртуальных функций неизменен для определенного и зависит от количества виртуальных функции. Точнее размер вт = кол-ву виртуальных. функции. (Естественно с учетом наследования т.е. вирт. ф. предков тоже считаютя). И изменить его можно только добавив/удалив вирт.ф-цию. - Что во время выполнения невозможно.

Тогда такой вопрос, каков размер таблицы виртуальных функций для java.lang.Object.toString()? smile

Во время выполнения добавляется класс (загрузка то динамическая), а вот он уже может содержать новые виртуальные функции и их приходится добавлять в таблицу. На этапе компиляции известно только какие функции виртуальны а какие нет.
В С++ все классы известны на этапе компиляции и поэтому можно сразу посчитать размер данной таблицы, но не в Java.
Добавлено @ 21:50
Цитата(MoonCat @ 21.3.2006, 21:40 Найти цитируемый пост)
А виртуальность функции безсмысленна без переопределения.

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


--------------------
Disclaimer: this post contains explicit depictions of personal opinion. So, if it sounds sarcastic, don't take it seriously. If it sounds dangerous, do not try this at home or at all. And if it offends you, just don't read it.
PM MAIL WWW   Вверх
powerOn
Дата 21.3.2006, 21:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


software saboteur
****


Профиль
Группа: Участник
Сообщений: 4367
Регистрация: 7.10.2005

Репутация: 47
Всего: 159



Цитата

Тогда такой вопрос, каков размер таблицы виртуальных функций для java.lang.Object.toString()? smile



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


--------------------
user posted image нет времени думать - нужно писать КОД!

PM MAIL   Вверх
LSD
Дата 21.3.2006, 22:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Leprechaun Software Developer
****


Профиль
Группа: Модератор
Сообщений: 15718
Регистрация: 24.3.2004
Где: Dublin

Репутация: 210
Всего: 538



ОК, залезем немного во внутренности.

Возьмем все тот же java.lang.Object.toString(), когда ты пишешь в программе o.toString(), то в код вставляется вызов метода toString() из java.lang.Object. Потом во время исполнения происходит вызов этого метода причем в него передаются, помимо объявленных параметров еще и указатель на this и таблица виртуальных функций. Далее в этой таблице находится адрес функции которую надо вызвать для данного класса (если не найдем, то в C++ получим Pure Virtual Function Call, в Java IncompatibleClassChangeError). Ну а потом уже все просто метод мы знаем и вызываем его smile


--------------------
Disclaimer: this post contains explicit depictions of personal opinion. So, if it sounds sarcastic, don't take it seriously. If it sounds dangerous, do not try this at home or at all. And if it offends you, just don't read it.
PM MAIL WWW   Вверх
Sherst
Дата 21.3.2006, 23:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 131
Регистрация: 26.10.2005

Репутация: нет
Всего: 2



MoonCat привел пример в котором есть строка

Код

A a2 = new B();
a2.meth(); // b meth call!     


Правильно ли я понимаю:
Во время исполнения происходит вызов метода meth() по таблице виртуальных ф-ий класса B (из-за new B()), в который передается указатель this(он говорит о том что meth() был вызван для объекта a2).

И почему тогда для static все наоборот?
PM MAIL   Вверх
LSD
Дата 21.3.2006, 23:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Leprechaun Software Developer
****


Профиль
Группа: Модератор
Сообщений: 15718
Регистрация: 24.3.2004
Где: Dublin

Репутация: 210
Всего: 538



Цитата(Sherst @ 21.3.2006, 23:04 Найти цитируемый пост)
Во время исполнения происходит вызов метода meth() по таблице виртуальных ф-ий класса B (из-за new B()), в который передается указатель this(он говорит о том что meth() был вызван для объекта a2).

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


Цитата(Sherst @ 21.3.2006, 23:04 Найти цитируемый пост)
И почему тогда для static все наоборот?

А в static функциях, нет переменной this. Поэтому тип вызываемой функции определяется на этапе компиляции, и определяется он по имени класса. Даже если вызывать его не по имени класса, а через переменную:
Код
A a2 = new B();    
a2.someStaticMethod(); //A.someStaticMethod() call!

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


--------------------
Disclaimer: this post contains explicit depictions of personal opinion. So, if it sounds sarcastic, don't take it seriously. If it sounds dangerous, do not try this at home or at all. And if it offends you, just don't read it.
PM MAIL WWW   Вверх
Sherst
Дата 21.3.2006, 23:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 131
Регистрация: 26.10.2005

Репутация: нет
Всего: 2



Теперь ясно.
Спасибо всем кто отозвался.
PM MAIL   Вверх
Sherst
Дата 22.3.2006, 00:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 131
Регистрация: 26.10.2005

Репутация: нет
Всего: 2



Забыл спросить smile

Как компилятор по таблице виртуальных ф-ий находит именно нужный нам метод?

PM MAIL   Вверх
chief39
Дата 22.3.2006, 11:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


карманная тигра
***


Профиль
Группа: Участник Клуба
Сообщений: 1631
Регистрация: 20.5.2005
Где: Киев

Репутация: 15
Всего: 77



Цитата(Sherst @ 22.3.2006, 00:07 Найти цитируемый пост)
Как компилятор по таблице виртуальных ф-ий находит именно нужный нам метод?

Нууу... трудно сказать какой там код - в написании JVM ещё не участвовал smile))

А если серьёзно - то компилятор не ищет по сей таблице(она юзается во время выполнения - не компиляции).
Он просто компилит, ничего не связывая. ТОЛЬКО если находит final - МОЖЕТ встроить жёстко тело метода вместо вызова его.

А во время выполнения он берёт объект некий. Определяет его класс. например иерархия A->B->C. Создал C. Вызываешь метод f(). JVM смотрит есть ли у класса С метод f(). Есть? - отлично, выполним его! Нету - смотрим у B. Есть? - выполним! Нету? - ещё выше смотрим.
Ну и не следует забывать о private и final. Если верхние методы будут private - то JVM вообще ничего не найдёт(вернее ты не сможешь вызывать такой метод ещё на этапе компиляции - верхние недоступны а нижестоящих - нету, иначе наверх бы не полезло). А если верхние будут final - то нижестоящие классы аналогичный метод не смогут поиметь ещё на этапе компиляции. То есть для всех наследников в роли такого метода будет вызываться именно этот родительский. А свой они создать не смогут - компилятор по жопе нашлёпает. smile
ЗЫ: когда подгружается класс - в таблицу его методы заносятся. А когда я говорил "ищем" или JVM "смотрит"- это по той самой таблице smile А вот как именно оно её итерирует - это уже проблемы разработчиков Sun smile Это ведь не суть важно для нас - главное что этот механизм предоставляет функциональность - а как... нас не волнует smile

Это сообщение отредактировал(а) chief39 - 22.3.2006, 11:06


--------------------
Люди - это свечи. Они либо горят, либо их - в жопу!(с)

PM MAIL   Вверх
powerOn
Дата 22.3.2006, 11:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


software saboteur
****


Профиль
Группа: Участник
Сообщений: 4367
Регистрация: 7.10.2005

Репутация: 47
Всего: 159



Цитата

ЗЫ: когда подгружается класс - в таблицу его методы заносятся. А когда я говорил "ищем" или JVM "смотрит"- это по той самой таблице smile




chief39, а как понять "смотрит", в том смысле как определяется что это имеено та функция что нам нужна, а ни какая нибудь другая?


--------------------
user posted image нет времени думать - нужно писать КОД!

PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Java"
LSD   AntonSaburov
powerOn   tux
javastic
  • Прежде, чем задать вопрос, прочтите это!
  • Книги по Java собираются здесь.
  • Документация и ресурсы по Java находятся здесь.
  • Используйте теги [code=java][/code] для подсветки кода. Используйтe чекбокс "транслит", если у Вас нет русских шрифтов.
  • Помечайте свой вопрос как решённый, если на него получен ответ. Ссылка "Пометить как решённый" находится над первым постом.
  • Действия модераторов можно обсудить здесь.
  • FAQ раздела лежит здесь.

Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux, javastic.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Java: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.1445 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.