IPB
ЛогинПароль:

> Правила раздела!

1. Заголовок или название темы должно быть информативным !
2. Все тексты фрагментов программ должны помещаться в теги [code] ... [/code] или [code=pas] ... [/code].
3. Прежде чем задавать вопрос, см. "FAQ" и используйте ПОИСК !
4. НЕ используйте форум для личного общения!
5. Самое главное - это раздел теоретический, т.е. никаких задач и программ (за исключением небольших фрагментов) - для этого есть отдельный раздел!

 
 Ответить  Открыть новую тему 
> ООП, Полиморфизм
сообщение
Сообщение #1


Профи
****

Группа: Пользователи
Сообщений: 865
Пол: Мужской
Реальное имя: Вячеслав

Репутация: -  20  +


Всем привет!
Начал изучать ООП и появились вопросы. Вроде с наследованием и инкапсуляцией понятно, а вот с полиморфизмом не понятно. Можете объяснить для чего он нужен и что такое виртуальные методы?
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #2


Гость






Ну, ты же здесь был: ООП. Объектно-ориентированное программирование ? Там написано ,что такое полиморфизм, и как он реализуется... Что-то непонятно?
 К началу страницы 
+ Ответить 
сообщение
Сообщение #3


Профи
****

Группа: Пользователи
Сообщений: 865
Пол: Мужской
Реальное имя: Вячеслав

Репутация: -  20  +


Цитата
Полиморфизм.
Возможность определения единого по имени действия (процедуры или функции), применимого одновременно ко всем объектам иерархии наследования, причем каждый объект может "заказывать" особенность реализации этого действия над "самим собой".
В наследовании есть родитель и потомок, где потомок сохраняет поля и методы родителя. А в полиморфизме наоборот?
Цитата
причем каждый объект может "заказывать" особенность реализации этого действия над "самим собой".
Это совсем не понятно(
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #4


Гость






Не путай теплое с мягким... Наследование - это необходимое условие полиморфизма, нельзя сделать полиморфность без наследования. Смотри:
type
ta = object
constructor init;
procedure print; virtual;
end;

constructor ta.init;
begin end;
procedure ta.print;
begin writeln('TA object') end;

procedure proc(var obj: ta);
begin
obj.print;
end;

type
tb = object(ta)
constructor init;
procedure print; virtual;
end;

constructor tb.init;
begin inherited init; end;
procedure tb.print;
begin writeln('TB object') end;

var
A: ta;
B: tb;
begin
a.init; proc(a);
b.init; proc(b);
end.
Чувствуешь? Proc принимает объект типа TA или его потомка (неважно, насколько далекого, может "сын", а может и "внук", "правнук" и т.д.), и вызывает метод нужного типа. То есть, для того, чтобы напечатать значение любого потомка достаточно "заказать" в определенном классе нужную тебе функциональность. Я "заказал" реализацию TB.print, что заказал, то и получил... Только наследованием (без виртуализации) этого добиться нельзя. Если в вышеприведенном примере не будет виртуальных методов, то процедура не будет полиморфной, она для любого переданного объекта будет вызывать метод TA.print...
 К началу страницы 
+ Ответить 
сообщение
Сообщение #5


Профи
****

Группа: Пользователи
Сообщений: 865
Пол: Мужской
Реальное имя: Вячеслав

Репутация: -  20  +


Цитата
Наследование - это необходимое условие полиморфизма, нельзя сделать полиморфность без наследования.
O_o незнал.
procedure proc(var obj: ta);
begin
obj.print;
end;
Понял, для каждого потомка будет свой метод smile.gif
constructor tb.init;
begin inherited init; end;

А что это такое inherited?
proc(b);
это тоже самое что и
b.print
Спасибо за помощь!
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #6


Гость






Цитата
А что это такое inherited?
Это вызов метода из непосредственного родителя... Можно, конечно, сделать так:
constructor tb.init;
begin ta.init; end;
, но подумай, что получится, если между TA и TB будет внесен еще один наследник. Было:
type
ta = object
end;
tb = object(ta)
end;
, стало:
type
ta = object
end;
ta2 = object(ta)
end;
tb = object(ta2)
end;
, тогда прямое указание ta.init придется поменять на ta2.init, если же использовался inherited - ничего менять не надо будет...

P.S.
Да, proc(b) и b.print будут выполнять одно и то же действие, если больше ты ничего не менял в программе.
 К началу страницы 
+ Ответить 
сообщение
Сообщение #7


Профи
****

Группа: Пользователи
Сообщений: 865
Пол: Мужской
Реальное имя: Вячеслав

Репутация: -  20  +


uses crt;
type
ta = object
constructor init;
procedure print; virtual;
end;

constructor ta.init;
begin end;
procedure ta.print;
begin writeln('TA object') end;

procedure proc(var obj: ta);
begin
obj.print;
end;

type
ta2 = object(ta)
constructor init;
procedure print; virtual;
end;

constructor ta2.init;
begin end;
procedure ta2.print;
begin writeln('TA2 object') end;


type
tb = object(ta2)
constructor init;
procedure print; virtual;
end;

constructor tb.init;
begin {inherited init;} end;
procedure tb.print;
begin writeln('TB object') end;

var
A: ta;
B: tb;
c:ta2;
begin
clrscr;
a.init; proc(a);
b.init; proc(b);
c.init; proc©;
readkey
end.
Цитата
но подумай, что получится, если между TA и TB будет внесен еще один наследник
Добавил наследника, закоментировал
inherited init;
все равно работает О_о
если я правильно понял про наследника


Добавлено через 4 мин.
Упс... Там же по идеи должны присваиваться какие-то значения полям, но их нету. Если были бы, то не прокатило, да?
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #8


Гость






Цитата
все равно работает О_о
Да, работает... Только некорректно это. При инициализации потомка надо сначала инициализировать предка. Ты этого не делаешь. Хочешь, набросаю пример программы, при котором БЕЗ вызова всей цепочки Init-ов получишь аварийный вылет? smile.gif
 К началу страницы 
+ Ответить 
сообщение
Сообщение #9


Профи
****

Группа: Пользователи
Сообщений: 865
Пол: Мужской
Реальное имя: Вячеслав

Репутация: -  20  +


Цитата
При инициализации потомка надо сначала инициализировать предка. Ты этого не делаешь
Инициализация?? т.е. присваивание полям значений или создание объекта?
Цитата
Хочешь, набросаю пример программы, при котором БЕЗ вызова всей цепочки Init-ов получишь аварийный вылет?
yes2.gif
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #10


Гость






Цитата
Инициализация?? т.е. присваивание полям значений или создание объекта?
И то и другое... Вот, например, при инициализации базового типа выделяется память под строку, а все остальные - передают в этот базовый тип результат своей инициализации: Прикрепленный файл  oop_01.pas ( 920 байт ) Кол-во скачиваний: 701


Где-нибудь цепочка Init-ов прервется - будет разыменование нулевого указателя, ошибка... Я надеюсь, понятно, что в конструкторе TA2, например, если какое-то дополнительное условие не выполняется, я могу поменять строку с 'no error' на любую другую? И в конструкторе TB тоже. И даже в TA...
 К началу страницы 
+ Ответить 
сообщение
Сообщение #11


Профи
****

Группа: Пользователи
Сообщений: 865
Пол: Мужской
Реальное имя: Вячеслав

Репутация: -  20  +


УРЯЯЯЯ!!! я понял) тут мы просто используем метод предка, т.е. если у предка 100 полей, а у потомка 2 доп. поля то можно вызвать метод предка по обработке полей и добавить действия над другими двумя полями)
Цитата
получишь аварийный вылет?
Что-то его нету blum.gif
Цитата
И то и другое...
В данном случае же есть экземпляр объекта, т.е. тут инициализация объекта это просто присваивание значений элементам?
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #12


Гость






Цитата
тут мы просто используем метод предка, т.е. если у предка 100 полей, а у потомка 2 доп. поля то можно вызвать метод предка по обработке полей и добавить действия над другими двумя полями)
Если ты про конструктор - то я тебе еще больше скажу: методы потомка ДОЛЖНЫ вызывать методы предка для инициализации/присвоения его (предка) полей, потому что никто не сможет инициализировать поле лучше, чем объект, в котором это поле добавляется.

Цитата
Что-то его нету
Чего нет? Вылета? Это не проблема ООП, это проблема Турбо-Паскаля... Любой нормальный компилятор при попытке разыменовать нулевой указатель вылетит с 216-ой ошибкой... Турбо-Паскаль же ошибку замалчивает (спрашивается, ЗАЧЕМ? Программа-то не работает правильнее от того, что не происходит вылет), но при этом печатает тебе на экране откровенный бред.
 К началу страницы 
+ Ответить 
сообщение
Сообщение #13


Профи
****

Группа: Пользователи
Сообщений: 865
Пол: Мужской
Реальное имя: Вячеслав

Репутация: -  20  +


Вроде понял) Спасибо за ответы!
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #14


Гость






Листинг программы от Дата 15.02.2009 17:01 содержит виртуальные методы. Как нужно настроить Borland Pascal 7.0 , чтобы он с ними корректно работал?
 К началу страницы 
+ Ответить 
сообщение
Сообщение #15


Гость






Никак не нужно настраивать, он по умолчанию прекрасно работает с виртуальностью. Если нет - меняй компилятор, у тебя кривая сборка.
 К началу страницы 
+ Ответить 
сообщение
Сообщение #16


Гость






А overload и override компилятор не понимает(. Это уже к Delphi?
 К началу страницы 
+ Ответить 

 Ответить  Открыть новую тему 
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 





- Текстовая версия 27.04.2024 23:37
500Gb HDD, 6Gb RAM, 2 Cores, 7 EUR в месяц — такие хостинги правда бывают
Связь с администрацией: bu_gen в домене octagram.name