Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Otvety_na_ekzamen_po_OOP.doc
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
293.89 Кб
Скачать

19. Совместимость типов

Паскаль – строго типизированный язык, т.е. например нельзя присвоить integer значение типа Boolean( можно использовать приведение типов. Правило: два значения совместимы по типу только тогда, они имеют одинаковый тип, т.е.ссылаются на одно и то же определение типа. )

Из этого правила существует следующее исключение: Если объявить класс, а затем объявить его потомка, то можно присваивать значение класса потомка, значению класса предка. ПРЕДОК=ПОТОМОК надо. ПОТОМОК=ПРЕДОК – нельзя.

Пример:

Type TAnimale = class //супер класс

Public

Constructor Create; // будет иниц. поле Kind

Function CutKind:string;

Private

Kind:string;

End;

TDog=class(TAnimale)

Public

Constructor Create; // будет присв.”Dog”

End;

Форма приложения, использующего эти классы, имеет частное поле myAnimal. Экземпляр этого класса создается при создании формы:

Procedure TformAnimals.FormCreate();

Begin

myAnimal:=TAnimal.Create;

End;

При выборе одного из переключателей:

Procedure TFormAnimals.RbtnDogClick(….);

Begin

myAnimal.Free;

myAnimal:=TDog.Create;

end; // самая расширенная совместимость типов! ПРЕДОК=ПОТОМОК.

Procedure TAnimals.BtnKindClick(…);

Begin

Kind.label.caption:=myAnimal.GetKind;

End;

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

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

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

Полиморфизм. Благодаря поддержке позднего связывания в Delphi реализуется важная концепция ООП – полиморфизм.

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

Пример: имеется переменная которая может ссылаться на объекты разных классов(см. пример выше про расширенную совместимость типов, эту переменную можно назвать полиморфным объектом, или универсальной переменной), для всех этих классов один и тот же метод может быть определен по разному.

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

Какому коду будет передано управление?(какой из версии метода?)-это зависит от того, к какому классу будет относиться объект, на который ссылается переменная в данный момент времени. Это можно определить только на момент выполнения программы.

Пример пример:

Имеются два класса Tanimal и Tdog, в них определен метод, имеющий позднее связывание, применим его к универсальной переменной MyAnimal, которая в процессе выполнения программы будет ссылаться то на экземпляр класса Tanimal, то на экземпляр класса TDog.

TAnimal = class

Public

Function Voice:string;virtual;

End;

Tdog = class(TAnimal)

Public

Function Voice:string;override;

Function TAnimal.Voice:string;

Begin

Voice:=’voice Animal’;

End;

Function TDog.Voice:string;

Begin

Voice:=’Gav-Gav’;

End;

MyAnimal:TAnimal;

……..

TFAnim.BtnVoice();

Begin

LbVoice.Caption:=MyAnimal.Voice;

End;

На этапе выполнения вызов MyAnimal.Voice приведет к следующему: если в момент вызова переменная ссылается на экземпляр класса TAnimal, будет вызван TAnimal.Voice, если же на экземпляр класса TDog, то будет вызван TDog.Voice. Такое поведение осуществляется за счет директив virtual и override.

Преимущества: вызов MyAnimal.Voice будет работать для экземпляра любого класса, который является потомком TAnimal, даже если он написан в другом модуле и даже если потомок вообще еще не написан. Чтобы определить вызов метода совместимым со всеми потомками базового класса компилятору не требуется никакой информации об этих потомках, ему требуется только класс предок.

Чтобы перекрыть виртуальный метод в классе потомке используется директива override. Чтобы перекрыть статический метод мы просто пишем метод с тем же самым методом. Можно вместо статического метода в потомке определить виртуальный метод с таким же именем, но они не будут уже никак связаны.

Type myclass = class

Procedure One; virtual;

Procedure TWD;

End;

mySubClass = class(myclass)

procedure one; override;

procedure Two;

end;

Существует 2 способа перекрытия методов:

1. Предполагает полную замену родительского метода

2. Заключается в добавлении некоторого кода.

mySubClass.One

…новый код…

Inherited;

End;

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

В Delphi(в обжект паскаль) поддерживается 2 различных варианта реализации позднего связывания.

1. Использование директивы virtual.

2. Можно использовать dynamic.

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

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]