- •3. Объектно-ориентированное программирование (ооп)
- •3.1. Краеугольные камни ооп
- •3.1.1. Что такое объект?
- •3.1.2. Концептуальный пример объекта
- •3.1.3. Природа объекта
- •3.1.4. Понятие класса объектов
- •3.1.5. Три кита ооп
- •3.1.6. Объекты и компоненты
- •3.2. Классы
- •3.2.1. Понятие класса
- •3.2.2. Классы в программных модулях
- •3.3. Объекты
- •3.4. Методы
- •3.4.1. Понятие метода
- •3.4.2. Конструкторы и деструкторы
- •3.5. Свойства
- •3.5.1. Понятие свойства
- •3.5.2. Методы получения и установки значений свойств
- •3.5.3. Свойства-массивы
- •3.5.4. Свойство-массив как основное свойство объекта
- •3.5.5. Методы, обслуживающие несколько свойств
- •3.6. Наследование
- •3.6.1. Понятие наследования
- •3.6.2. Прародитель всех классов
- •3.6.3. Перекрытие атрибутов в наследниках
- •3.6.4. Совместимость объектов различных классов
- •3.6.5. Контроль и преобразование типов
- •3.7. Статические методы
- •3.7.1. Понятие статического метода
- •3.8. Виртуальные методы
- •3.8.1. Понятие виртуального метода
- •3.8.2. Механизм вызова виртуальных методов
- •3.8.3. Абстрактные виртуальные методы
- •3.8.4. Динамические методы
- •3.8.5. Методы обработки сообщений
- •3.9. Указатели на методы объектов
- •3.12. Метаклассы
- •3.12.1. Ссылки на классы
- •3.12.2. Методы классов
- •3.12.3. Виртуальные конструкторы
- •3.13. Классы общего назначения
- •3.13.1. Классы для представления списка строк
- •Свойства:
- •Методы:
- •События:
- •3.13.2. Классы для представления потока данных
- •Общие свойства:
- •Общие методы:
- •3.14. Итоги
- •4. Исключительные ситуации и надежное программирование
- •4.1. Ошибки и исключительные ситуации
- •4.2. Классы исключительных ситуаций
- •4.3. Обработка исключительных ситуаций
- •4.3.1. Создание исключительной ситуации
- •4.3.2. Распознавание класса исключительной ситуации
- •4.3.3. Пример обработки исключительной ситуации
- •4.3.4. Возобновление исключительной ситуации
- •4.3.5. Доступ к объекту, описывающему исключительную ситуацию
- •4.4. Защита выделенных ресурсов от пропадания
- •4.4.1. Утечка ресурсов и защита от нее
- •4.5. Итоги
3.4. Методы
3.4.1. Понятие метода
Процедуры и функции, предназначенные для выполнения над объектами действий, называются методами. Предварительное объявление методов выполняется при описании класса в секции interface модуля, а их программный код записывается в секции implementation.
Однако в отличие от обычных процедур и функций заголовки методов должны иметь уточненные имена, т.е. содержать наименование класса. Приведем пример реализацию одного из методов в классе TFigure:
Procedure TFigure.Move (NewX,NewY:Integer); Begin Hide; Coords.X:=NewX; Coords.Y:=NewY; Draw; End; |
Обратите внимание, что внутри методов обращения к полям и другим методам выполняются как к обычным переменным и подпрограммам без уточнения экземпляра объекта. Такое упрощение достигается путем использования в пределах метода псевдопеременной Self (стандартный идентификатор). Физически Self представляет собой дополнительный неявный параметр, передаваемый в метод при вызове. Этот параметр и указывает экземпляр объекта, к которому данный метод (Move) применяется.
Практика показывает, что псевдопеременная Self редко используется в явном виде. Ее необходимо применять только тогда, когда при написании метода может возникнуть какая-либо двусмысленность для компилятора, например при использовании одинаковых имен и для локальных переменных, и для полей объекта.
3.4.2. Конструкторы и деструкторы
Особой разновидностью методов являются конструкторы и деструкторы. Напомним, что конструкторы создают, а деструкторы разрушают объекты. Создание объекта включает выделение памяти под экземпляр и инициализацию его полей, а разрушение — очистку полей и освобождение памяти.
Действия по инициализации и очистке полей специфичны для каждого конкретного класса объектов. По этой причине язык Delphi позволяет переопределить стандартный конструктор Create и стандартный деструктор Destroy для выполнения любых полезных действий. Можно даже определить несколько конструкторов и деструкторов (имена им назначает сам программист), чтобы обеспечить различные процедуры создания и разрушения объектов.
Объявление конструкторов и деструкторов похоже на объявление обычных методов с той лишь разницей, что вместо зарезервированных слов function и procedure используются слова constructor и destructor. Для нашего класса TFigure потребуется конструктор, которому в качестве параметра будет передаваться начальная позиция объекта:
Type TFigure = class ... // Конструкторы и деструкторы constructor Create(const Left,Top:integer); destructor Destroy; override; ... end; |
Приведем их возможную реализацию:
constructor TFigure.Create(const Left,Top:integer); begin Coords.x:=left; Coords.y:=top; end;
destructor TFigure.Destroy; begin // Пока ничего не делаем end; |
Если объект содержит встроенные объекты или другие динамические данные, то конструктор — это как раз то место, где их нужно создавать.
Конструктор применяется к классу или к объекту. Если он применяется к классу,
Figure := TFigure.Create(100,200); |
то выполняется следующая последовательность действий:
в динамической памяти выделяется место для нового объекта;
выделенная память заполняется нулями. В результате все числовые поля и поля порядкового типа приобретают нулевые значения, строковые поля становятся пустыми, а поля, содержащие указатели и объекты получают значение nil;
затем выполняются заданные программистом действия конструктора;
ссылка на созданный объект возвращается в качестве значения конструктора. Тип возвращаемого значения совпадает с типом класса, использованного при вызове (в нашем примере это тип TDelimitedReader).
Если конструктор применяется к объекту,
Figure.Create(100,200); |
то конструктор выполняется как обычный метод. Другими словами, новый объект не создается, а происходит повторная инициализация полей существующего объекта. В этом случае конструктор не возвращает никакого значения. Далеко не все объекты корректно себя ведут при повторной инициализации, поскольку программисты редко закладывают такую возможность в свои классы. Поэтому на практике повторная инициализация применяется крайне редко.
Деструктор уничтожает объект, к которому применяется:
Figure.Destroy; |
В результате:
выполняется заданный программистом код завершения;
освобождается занимаемая объектом динамическая память.
В теле деструктора обычно должны уничтожаться встроенные объекты и динамические данные, как правило, созданные конструктором.
Как и обычные методы, деструктор может иметь параметры, но эта возможность используется редко.