
- •Введение
- •Начальные сведения о программах на языке Pascal
- •Структура Pascal-программы
- •Внешний вид исходного текста программы
- •Простейшие операторы
- •Ввод и вывод: консоль
- •Типы данных и операции
- •Операции и выражения
- •Приведение типов данных
- •Операции
- •Составной оператор
- •Инструкции выбора
- •Процедуры и функции
- •Множества
- •Сортировки массивов
- •Улучшенные сортировки
- •Рекурсия
- •Модуль GraphAbc
- •Указатели в Паскале
- •Динамически распределяемая память
- •Динамические структуры данных
- •Списочные структуры
- •Текстовые файлы
- •Бинарные файлы
- •Типизированные файлы
- •Нетипизированные файлы
- •Элементы комбинаторики
- •Матрица смежности.
- •2. Массив ребер.
- •3. Списки инцидентности.
- •4. Списки смежности.
- •Части графа.
- •Методы обхода графа.
- •Поиск в глубину.
- •Поиск в ширину.
- •Поиск кратчайших путей.(Алгоритм Дейкстры).
- •Основы ооп
- •Классы объектов
- •Принципы ооп
- •Создание и уничтожение объектов
- •Полиморфизм и наследование в Delphi
- •Наследование
- •Полиморфизм
- •Статическое замещение методов.
- •2) Перегрузка
- •Интегрированная среда разработки Delphi 7
- •Стандартные компоненты Delphi
- •Дополнительные компоненты
- •Другие дополнительные компоненты
- •Компоненты 32-разрядного интерфейса
- •Коллекция картинок
- •2 Индикатор выполнения
- •3 Ползунок
- •Реверсивный счетчик UpDown
- •Редактор горячих клавиш
- •Компоненты для работы с датами
- •Строка состояния
- •8 Панель инструментов
- •9 Элементы с вкладками
- •10 Компонент RichEdit
- •Компоненты вкладки Dialogs Страница Dialogs
- •Диалог выбора шрифта — компонент FontDialog
- •Диалог выбора цвета — компонент ColorDialog
- •Диалоги печати и установки принтера — компоненты PrintDialog и PrinterSetupDialog
- •Диалоги поиска и замены текста — компоненты FindDialog и ReplaceDialog
- •Страница Samples
- •Графические возможности Delphi 7
- •Формирование изображений программным способом
- •Мультимедиа-возможности Delphi
- •Компонент Animate
- •Компонент MediaPlayer
- •Воспроизведение звука
- •Просмотр видеороликов и анимации
- •Компоненты доступа к базам данных. Компоненты представленя данных.
Создание и уничтожение объектов
Как создаются и уничтожаются объекты? Объект "появляется на свет" в результате вызова специального метода, который инициализирует объект — конструктора. Созданный экземпляр уничтожается другим методом — деструктором:
AMyObject := TMyObject.Create;
{ действия с созданным объектом }
AMyObject.Destroy;
Создание объекта включает выделение памяти под экземпляр и инициализацию его полей, а разрушение — очистку полей и освобождение памяти. Однако обратите внимание, что вызывается метод TMyObject. Create, a нe AMyObject. Create. В Object Pascal экземпляры объектов могут быть только динамическими. Это означает, что в приведенном выше фрагменте переменная AMyObject на самом деле является указателем, содержащим адрес объекта.
В Object Pascal конструкторов у класса может быть несколько. Общепринято называть конструктор Сreate. Типичное название деструктора — Destroy.
type
TMyObject = class(TObject)
MyField: Integer;
Constructor Create;
Destructor Destroy;
Function MyMethod: Integer;
end;
Для уничтожения экземпляра объекта рекомендуется использовать метод Free, который первоначально проверяет указатель (не равен ли он nil) и только затем вызывает Destroy:
AMyObject.Free;
До передачи управления телу конструктора происходит собственно создание объекта — под него отводится память, значения всех полей обнуляются. Далее выполняется код конструктора, написанный программистом для инициализации экземпляров данного класса. Таким образом, хотя на первый взгляд синтаксис конструктора схож с вызовом процедуры (не определено возвращаемое значение), но на самом деле конструктор — это функция, возвращающая созданный и проинициализированный объект.
Конструктор создает новый экземпляр объекта только в том случае, если перед его именем указано имя класса. Если указать имя уже существующего объекта, он поведет себя по-другому: не создаст новый экземпляр, а только выполнит код, содержащийся в теле конструктора.
Объявление конструкторов и деструкторов похоже на объявление обычных методов с той лишь разницей, что вместо зарезервированного слова procedure (или function) используются слова constructor и destructor:
Code: |
type TDiskGauge = class DriveLetter: Char; PercentCritical: Integer; constructor Create; destructor Destroy; ... end; |
Приведем их возможную реализацию:
Code: |
constructor TDiskGauge.Create; begin DriveLetter := 'C'; PercentCritical := 10; end; destructor TDiskGauge.Destroy; begin { Разрушение встроенных объектов и освобождение динамических данных} end; |
Конструктор иногда имеет параметры, в которых передаются исходные значения полей объекта. Если объект содержит встроенные объекты или другие динамические данные, то конструктор — это как раз то место, где их нужно создавать.
Конструктор применяется к классу или к объекту. Если он применяется к классу
Code: |
DiskGauge: = TDiskGauge.Create; |
то выполняется следующая последовательность действий:
• |
в динамической памяти выделяется место для нового объекта; |
• |
выделенная память заполняется нулями; в результате все числовые поля и поля порядкового типа приобретают нулевые значения, строковые поля становятся пустыми, а поля, содержащие указатели и объекты, получают значение nil; |
• |
затем выполняются заданные программистом действия конструктора; |
• |
ссылка на созданный объект возвращается в качестве значения конструктора; тип возвращаемого значения совпадает с типом класса, использованного при вызове (в нашем примере это тип TDiskGauge). |
Если конструктор применяется к объекту (DiskGauge.Create;)то новый объект не создается, а происходит переинициализация полей существующего. В этом случае конструктор не возвращает никакого значения.
Деструктор уничтожает объект, к которому применяется (DiskGauge.Destroy;)
В результате:
• |
выполняется заданный программистом код деинициализации; |
• |
освобождается занимаемая объектом динамическая память. |
В теле деструктора обычно должны уничтожаться встроенные объекты и динамические данные, созданные конструктором.
В самом начале предыдущего примера мы использовали метод Create для создания экземпляра класса TUser, а в конце - метод Destroy для его удаления, хотя сами эти методы определены в классе не были. Но вспомним, что в ООП существует такое понятие, как наследование, а все классы в Delphi происходят от класса TObject. Именно по наследству от TObject классу TUser эти методы и достались.
Метод Create является конструктором класса, т.е. подпрограммой, создающий объект (экземпляр класса) в памяти. В том случае, если при создании экземпляра класса никаких дополнительных действий производить не требуется, используют метод Create, доставшийся от родительского класса. Если же при создании объекта требуется выполнить какие-либо действия, то метод Create переписывают заново. Например, если при инициализации класса TUser нам надо было бы задать какие-либо имя пользователя и пароль по умолчанию, то мы могли бы определить конструктор заново:
type TUser = class
...
constructor Create;
end;
constructor TUser.Create;
begin inherited Create;
fLogin:='User';
fPassword:='password';
end;
Обратите внимание на то, что, во-первых, конструктор - это не процедура и не функция, а именно конструктор, и задается, соответственно, при помощи ключевого слова constructor, а во-вторых, в самом теле подпрограммы-конструктора первым делом производится вызов родительского конструктора при помощи ключевого слова inherited. Таким образом, унаследованный метод выполняет всю необходимую для начальной инициализации объекта работу. Как нетрудно догадаться, это возможно благодаря такой концепции ООП, как полиморфизм.
Есть всего одно условие, касающееся расположения конструкторов и деструкторов в объявлении класса: они должны быть объявлены в общедоступной части, т.е. в public или в published.
Однако просматривая исходные коды других программ (включая библиотеку VCL) вы вряд ли обнаружите вызов метода Destroy напрямую. Дело в том, что к моменту уничтожения того же объекта TUser поле MegaInfo уже может быть освобождено, например, путем присвоения ему в программе значения "nil" (нулевого указателя):
User.MegaInfo:=nil; User.Destroy; // здесь во время выполнения возникнет ошибка! Таким образом, попытка повторно освободить память при помощи метода Destroy приведет к ошибке выполнения программы. Поэтому на практике, вместо метода Destroy всегда используют метод Free, который сначала проверяет, не является ли ссылка на объект нулевым указателем, и если нет - то только тогда вызывает деструктор. Соответственно, вид деструктора и его вызов из программы будут выглядеть таким вот образом: destructor TUser.Destroy; begin ... MegaInfo.Free; inherited Destroy; end; ... User.MegaInfo:=nil; User.Free; // теперь ошибки не будет
Таким образом, использование метода Free является прекрасной возможностью избежать непредвиденных ошибок времени выполнения.
Конструкторы и деструкторы, подобно другим подпрограммам, могут принимать значения в качестве параметров. Например, если при создании нового экземпляра класса TUser нам нужно было бы сразу получить его имя, то конструктор получился бы таким:
constructor TUser.Create(str: string);
begin
inherited Create;
fLogin:=str;
fPassword:='password';
end;
Соответственно, создание объекта типа TUser в программе теперь будет выглядеть следующим образом:
User:=TUser.Create('Вася');
Аналогичным образом параметры можно передавать и деструкторам, при этом, в зависимости от значения параметров, они могут, скажем, выполнять или не выполнять перед уничтожением объекта какие-либо действия, вроде сохранения данных на диск, вывода того или иного сообщения и т.д.