- •1. Новые концепции ооп в языке Oblect Pascal
- •2. Объектно-ориентированный подход в программировании
- •Основные понятия
- •3. Понятие класса и объекта
- •4. Поля, методы и свойства объекта
- •5. Ключевое слово Self, примеры использования
- •6. Перегруженные методы
- •7. Создание и удаление объектов
- •8. Инкапсуляция
- •9. Инкапсуляция и модули
- •10. Директивы видимости
- •11. Инкапсуляция при помощи свойств
- •12. Свойства-массивы
- •13. Индексированные свойства
- •14. Свойства и иерархия классов
- •15. Конструкторы, перегрузка конструкторов, 16. Деструкторы
- •17. Ссылочная модель объектов Delphi
- •18. Наследование
- •19. Совместимость типов
- •20. Полиморфизм и позднее связывание
- •21. Виртуальные, динамические методы
- •22. Абстрактные методы
- •23. Бе6зопасное преобразование типов
- •24. Ссылки на класс
- •25. Создание компонентов при помощи ссылок на класс
- •26. Интерфейсы
- •27. Технические приемы, связанные с использованием интерфейсов (делегирование, использование директивы implements)
- •28. Исключительные ситуации
- •29. Порядок выполнения программы и блок finally
- •30. Классы исключений
- •31. Исключения и отладка приложений
- •32. Класс tObject, использование методов класса Tobject
- •33. Понятие события
- •34. Обработчики событий. Делегирование в Delphi
- •35. События стандартных визуальных компонент и их использование
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.
Синтаксис и результат выполнения в обоих случаях одинаковые. Различия заключаются во внутреннем механизме, используемом компилятором для реализации позднего связывания.
