Перекрытие стандартных методов

Delphi 7. Занятие 2_7. Часть 5.

Задачи занятия.

  • понятие модального окна;
  • перекрытие метода класса в потомке;
  • пример элементов программы, рассмотренной в следующем занятии;
  • программное создание компонента и его размещение на форме.

Как мы говорили ранее, родоначальником всех объектов является прородитель класс Tobject, который сам по себе мало что может. Но он выступает в качестве корня, из которого вырастает дерево конкретного объекта.

Каждый последующий класс иерархии добавляет новые возможности за счет включения новых методов и полей.

Перекрытие методов

Иногда необходимо переопределить результаты работы метода, оставив прежним его имя. В этом случае вступает в силу механизм замещения метода, или, как говорят по другому — перекрытие метода в потомке.

В этом случае старый метод замещается новым на этапе компиляции программы, при этом старый метод становится недоступным.

Пример программы с перекрытием метода.

type
TMyClassA=class
procedure pr(i:integer);
end;

TMyClassB=class(TMyClassA)
procedure pr(s:string=’ВЫЗОВ БЕЗ ПАРАМЕТРА’);
end;

procedure TMyClassA.pr(i:integer);
var s:string;
begin
s:=intToStr(i);
showMessage(‘процедура pr класса TMyClassA’+#13#10+’ обрабатывает целое значение,’#13#10+’равное ‘+s);
end;

Модальные окна в delphi

Окна (формы), создаваемые делфи, можно открывать и закрывать независимо друг от друга. Их можно открыть одновременно и произвольно располагать на экране.

Однако существует тип окна, который ведёт себя по-другому. Это так называемое модальное окно. Например showMessage;

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

Открыть окно в модальном режиме можно с помощью команды showModul.

Продолжение листинга

procedure TmyClassB.pr(s:string=’ВЫЗОВ БЕЗ ПАРАМЕТРА’);
//переопределяем метод pr. Заменяем тип параметра и вводим значение по умолчанию.
begin
showMessage(‘процедура pr переопределена в классе TmyClassB’+#13#10+’обрабатывает строковое значение. ‘+#13#13#10+s); //#13#13 — дважды переводим строку вниз
//Не забывайте, что окно сообщения showMessage модальное. Пока оно не будет закрыто, другие действия с программой невозможны!
end;

procedure TForm1.Button1Click(Sender: TObject);
var vA:TMyClassA; ii:integer;
begin
vA:=TMyClassA.Create;
ii:=form1.SpinEdit1.Value;
vA.pr(ii);
end;

procedure TForm1.Button2Click(Sender: TObject);
var vB:TMyClassB;
begin
vB:=TMyClassB.Create;
vB.pr; //вызов процедуры без параметра. Это возможно, так как в процедуре формальный параметр имеет значение по умолчанию.
end;

procedure TForm1.Button3Click(Sender: TObject);
var vB:TMyClassB;
begin
vB:=TMyClassB.Create;
vB.pr(#13#10+’ ВЫЗОВ С ПАРАМЕТРОМ’); //вызов процедуры с параметром
end;

Результат вызова процедуры pr из экземпляра объекта типа TmyClassA

перекрытие стандартных методов

Результат вызова процедуры pr из экземпляра объекта типа TmyClassBбез параметра и с параметром:

перекрытие стандартных методов
перекрытие стандартных методов

Но иногда удобно, чтобы метод с одним и тем же именем и одинаковым набором параметров работал по разному в зависимости от контекста.

Это так называемые виртуальные методы (или их разновидность — динамические методы).

Чтобы рассмотреть это на примере, надо пройти несколько этапов.

Программное создание компонента.

Ранее мы использовали компонент TPanel (панель) и компонент Timage (изображение) из панели компонентов.

Но это не единственная возможность расположить компонент на форме, а в некоторых случаях и не самая лучшая.

Визуальный компонент может быть создан программно.

Программный код, содержащий описание класса TPanel, содержится в модуле ExtCtrls. Название модуля ExtCtrls необходимо добавить в предложение Uses:

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;

Замечание. Ссылка на ExtCtrls будет автоматически добавлена в uses, если разместить на форме компонент TPanel и откомпилировать проект. Далее компонент можно удалить — ссылка всё равно останется в uses.

implementation
{$R *.dfm}
var vPan:TPanel; //вводим глобальную переменную
procedure TForm1.Button1Click(Sender: TObject);
begin
vPan:=TPanel.Create(form1); //вызываем конструктор Create, который создаёт в динамической памяти экземпляр компонента «панель».

В качестве аргумента указан компонент form1. Это значит, что форма будет являться «владельцем» создаваемого компонента «панель». В Delphi владелец отвечает за уничтожение всех принадлежащих ему объектов перед тем, как сам владелец будет уничтожен.

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

Если объём компонентов большой или их в сеансе работы приложения создаётся много, то произойдёт так называемая «утечка памяти», то есть память может закончиться, что приведёт зависанию системы.

Поэтому необходимо производить принудительную очистку динамической памяти. Наиболее удобный способ — вызвать процедуру FreeAndNil(объект).

vPan.Parent:=form1; //Компоненты должны реагировать на события. Например, на нажатие клавиш, клики мыши и на множество других. Но Delphi напрямую не может реагировать на все эти события.

На произошедшее событие откликается операционная система. Она формирует так называемые сообщения, которые оформляются в виде процедур. Ссылки на эти процедуры образуют очередь, которая называется очередью сообщений. Эта очередь доступна приложениям.

Delphi циклически обращается к этой очереди и обрабатывает находящиеся в ней сообщения.

Благодаря этому, например, приложению становится известно, какая клавиша или сочетания клавишей были нажаты.

Программа в Delphi представлена корневым (родительским) объектом Application. Формы являются дочерними по отношению к Application объектами. Компоненты, расположенные на формах, — это дочерние по отношению к форме объекты. И так далее.

Не надо путать дочерний объект и наследника (потомка).

Например, наследником класса TForm является класс TForm1=class( TForm).

Форма имеет доступ к поступающим в приложение сообщениям. Если расположенный на форме компонент объявлен дочерним по отношению к форме, то форма передает поступающие в неё сообщения (надо заметить, что не все компоненты обладают механизмом приёма сообщений).

Второй наиважнейший момент — родительский компонент (в частности форма) отвечает за отрисовку дочернего визуального компонента в рамках своего окна.

За указание родительского компонента отвечает свойство объекта «Parent».

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

Ещё раз, при создании нового класса производный класс также часто называют дочерним, а базовый класс — родительским.

Если мы хотим, например, добавить новые свойства кнопке, то она будет наследоваться от Tbutton.

В то же время в качестве родителя назначается форма (или через свойство parent: vPan.Parent:=form1; или автоматически в момент размещения компонента из палитры компонентов на форме).

vPan.Left:=200; // координата левого края панели
vPan.Top:=100; // координата верхнего края панели
vPan.Color:=clRed; //красный цвет поверхности панели
Vpan.Width:=420; //ширина панели
Vpan.Height:=320;//высота панели
end;

Ещё раз представим код без комментариев:

implementation

{$R *.dfm}

var vPan:TPanel;

procedure TForm1.Button1Click(Sender: TObject);
begin
vPan:=TPanel.Create(form1);
vPan.Parent:=form1;
vPan.Left:=200;
vPan.Top:=100;
vPan.Color:=clRed;
Vpan.Width:=420;
Vpan.Height:=320;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
FreeAndNil(vPan); //процедура уничтожает объект (освобождает динамическую память) и присваивает переменной vPan значение nil.
end;

Аналогично создаётся объект TImage.

Var vIm:TImage;

vIm:=TImage.Create(form1);// владелец form1

vIm.Parent:=vPan;// родителем для компоненты TImage назначается панель, поэтому компонент Timage будет расположен и отображён на панели.

В результате будем иметь:

перекрытие стандартных методов

На компоненте TPanel (красный) размещён компонент TImage (сиреневый).

Полный код проекта будет представлен в следующей части 5 занятия 2_7.

Обновлено: 01.02.2021 — 10:40

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *