Методы в Delphi

Методы в Delphi

  1. Обзор
  2. Чтобы полностью понять и почувствовать все преимущества Delphi, Вам
    нужно хорошо изучить язык Object Pascal. И хотя возможности визуальной
    части Delphi чрезвычайно богаты, хорошим программистом может стать только
    тот, кто хорошо разбирается в технике ручного написания кода.

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

  3. Создание
    методов с помощью визуальных средств
  4. В предыдущем уроке Вы видели,
    что синтаксический “скелет” метода может быть сгенерирован с помощью визуальных
    средств. Для этого, напомним, нужно в Инспекторе Объектов дважды щелкнуть
    мышкой на пустой строчке напротив названия интересующего Вас события в
    требуемом компоненте. Заметим, если эта строчка не пуста, то двойной щелчок
    на ней просто переместит Вас в окне Редактора Кода в то место, где находится
    данный метод.

    Для более глубокого понимания
    дальнейшего изложения кратко остановимся на концепции объектно-ориентированного
    программирования. Для начала определим базовое понятие объектно-ориентированного
    программирования – класс. Класс – это
    категория объектов, обладающих одинаковыми свойствами и поведением. При
    этом объект представляет собой просто экземпляр какого-либо
    класса. Например, в Delphi тип “форма” (окно) является классом, а переменная
    этого типа – объектом. Метод – это процедура, которая определена как часть
    класса и инкапсулирована (содержится) в нем. Методы манипулируют полями
    и свойствами классов (хотя могут работать и с любыми переменными) и имеют
    автоматический доступ к любым полям и методам своего класса. Доступ
    к полям и методам других классов зависит от уровня “защищенности” этих
    полей и методов. Пока же для нас важно то, что методы можно создавать как
    визуальными средствами, так и путем написания кода вручную.

    Давайте рассмотрим процесс
    создания программы CONTROL1, которая поможет нам изучить технику написания
    методов в Delphi.

    Для
    создания программы CONTROL1 поместите с помощью мышки компонент Edit
    (находится на страничке “Standard” Палитры Компонентов) на форму. После
    этого ваша форма будет иметь вид, показанный на 8.

    Теперь перейдите в Object
    Inspector, выберите страничку “Events” и дважды щелкните в пустой строчке
    напротив события OnDblClick,
    как показано на 8. После этого в активизировавшемся
    окне Редактора Вы увидите сгенерированный “скелет” метода Edit1DblClick,
    являющегося реакцией на событие OnDblClick:

    procedure TForm1.Edit1DblClick(Sender:
    TObject);

    begin

    end;

    После генерации процедуры
    Вы можете оставить ее имя таким, каким “установил” Delphi, или изменить
    его на любое другое (для этого просто введите новое имя в указанной выше
    строке Инспектора Объектов справа от требуемого события и нажмите Enter).

    Теперь в окне Редактора Кода
    введите смысловую часть метода:

    procedure TForm1.Edit1DblClick(Sender:
    TObject);

    begin

    Edit1.Text:= ‘Вы дважды щелкнули в строке
    редактирования’;

    end;

    Сохраните программу. Во время
    выполнения дважды щелкните на строке редактирования. Текст в этой строке
    изменится в соответствии с тем, что мы написали в методе Edit1DblClick:
    см. 8.

    Рис.
    -C: Содержимое управляющего элемента TEdit
    изменяется после двойного щелчка по нему

    8 и 8
    предоставляют полный код программы CONTROL1.
    Листинг
    -A: Программа CONTROL1 демонстрирует, как создавать и использовать методы
    в Delphi.

    program Control1;

    uses

    Forms,

    Main in ‘MAIN.PAS’ {Form1};

    begin

    Application.CreateForm(TForm1, Form1);

    Application.Run;

    end.
    Листинг
    -B: Головной модуль программы CONTROL1.

    unit Main;

    interface

    uses

    WinTypes, WinProcs,

    Classes, Graphics, Controls,

    Printers, Menus, Forms, StdCtrls;

    type

    TForm1 = class(TForm)

    Edit1: TEdit;

    procedure Edit1DblClick(Sender: TObject);

    end;

    var

    Form1: TForm1;

    implementation

    {$R *.DFM}

    procedure TForm1.Edit1DblClick(Sender: TObject);

    begin

    Edit1.Text := ‘Вы дважды щелкнули в строке
    редактирования’;

    end;

    end.

    После того, как Ваша программа
    загрузится в память, выполняются две строчки кода в CONTROL1.DPR, автоматически
    сгенерированные компилятором:

    Application.CreateForm(TForm1, Form1);

    Application.Run;

    Первая строка запрашивает
    память у операционной системы и создает там объект Form1,
    являющийся экземпляром класса TForm1.
    Вторая строка указывает объекту Application,
    “по умолчанию” декларированному в Delphi, чтобы он запустил на выполнение
    главную форму приложения. В данном месте мы не будем подробно останавливаться
    на классе TApplication
    и на автоматически создаваемом его экземпляре – Application.
    Важно понять, что главное его предназначение – быть неким ядром, управляющим
    выполнением Вашей программы.

    Как правило, у большинства
    примеров, которыми мы будем оперировать в наших уроках, файлы проектов
    .DPR
    практически одинаковы. Поэтому в дальнейшем там, где они не отличаются
    кардинально друг от друга, мы не будем приводить их текст. Более того,
    в файл .DPR, автоматически генерируемый
    Delphi, в большинстве случаев нет необходимости заглядывать, поскольку
    все действия, производимые им, являются стандартными.

    Итак, мы видели, что большинство
    кода Delphi генерирует автоматически. В большинстве приложений все, что
    Вам остается сделать – это вставить одну или несколько строк кода, как
    в методе Edit1DblClick:

    Edit1.Text := ‘Вы дважды щелкнули в строке
    редактирования’;

    Хотя внешний интерфейс программы
    CONTROL1 достаточно прост, она (программа) имеет строгую внутреннюю структуру.
    Каждая программа в Delphi состоит из файла проекта, имеющего расширение
    .DPR
    и одного или нескольких модулей, имеющих расширение .PAS.
    Модуль, в котором содержится главная форма проекта, называется головным.
    Указанием компилятору о связях между модулями является предложение Uses,
    которое определяет зависимость модулей.

    Нет никакого функционального
    различия между модулями, созданными Вам в Редакторе, и модулями, сгенерированными
    Delphi автоматически. В любом случае модуль подразделяется на три секции:

    ·Заголовок

    ·Секция
    Interface

    ·Секция
    Implementation

    Таким образом, “скелет” модуля
    выглядит следующим образом:

    unit Main; {Заголовок
    модуля}

    interface {Секция Interface}

    implementation {Секция Implementation}

    end.

    В интерфейсной секции (interface)
    описывается
    все то, что должно быть видимо для других модулей (типы, переменные, классы,
    константы, процедуры, функции). В секции implementation
    помещается код, реализующий классы, процедуры или функции.

  5. Передача
    параметров

Содержание урока
8:

Обзор

Создание методов с помощью визуальных средств

Передача параметров

Более сложные методы и управляющие элементы

Информация периода выполнения. Программа CONTROL3

Заключение

В Delphi процедурам и функциям
(а, следовательно, и методам классов) могут передаваться параметры для
того, чтобы обеспечить их необходимой для работы информацией. Программа
PARAMS демонстрирует, как использовать передачу параметров в методы Delphi.
Кроме того, мы узнаем, как:
·создавать
свои собственные процедуры

·добавлять
процедуру в класс, формируя метод класса

·вызывать
одну процедуру из другой.

Программа PARAMS позволяет Вам
вводить фразы в строки редактирования. После нажатия кнопки “Вызов процедуры
WriteAll”
строка из управляющего элемента EditSource
скопируется в шесть управляющих элементов – строк редактирования, как показано
на 8.

Далее мы не будем подробно
останавливаться на том, как размещать компоненты на форме – считаем, что
это Вы уже умеете. После того как Вы разместили на форме семь компонентов
Edit,
переименуйте с помощью Инспектора Объектов седьмой компонент (Edit7)
в EditSource.
Положите на форму компонент Button,
и в Object Inspector измените его заголовок (свойство Caption)
на “Вызов процедуры WriteAll” (естественно, Вы можете заменить его
шрифт, цвет и т.д.).

После завершения проектирования
формы класс TForm1
будет выглядеть следующим образом:

TForm1 = class(TForm)

Edit1: TEdit;

Edit2: TEdit;

Edit3: TEdit;

Edit4: TEdit;

Edit5: TEdit;

Edit6: TEdit;

EditSource: TEdit;

Button1: TButton;

end;

Следующий шаг состоит в добавлении
метода, вызываемого по нажатию пользователем кнопки Button1.
Это, напомним, можно сделать двумя способами:

  • Перейти
    в Инспекторе Объектов на страничку “Events” (предварительно выбрав компонент
    Button1 на форме), выбрать слово OnClick
    и дважды щелкнуть мышкой на пустой строчке справа от него
  • Просто дважды щелкнуть на компоненте
    Button1 на форме.

Delphi сгенерирует следующую
“заготовку”:

procedure TForm1.Button1Click(Sender:
TObject);

begin

end;

Цель программы PARAMS – научить
Вас писать процедуры и передавать в них параметры. В частности, программа
PARAMS реагирует на нажатие кнопки Button1
путем вызова процедуры WriteAll
и передачи ей в качестве параметра содержимого строки редактирования EditSource
(EditSource.Text).

procedure TForm1.Button1Click(Sender:
TObject);

begin

WriteAll(EditSource.Text);

end;

Важно понять, что объект
EditSource
является экземпляром класса TEdit
и, следовательно, имеет свойство Text,
содержащее набранный в строке редактирования текст. Как Вы уже, наверное,
успели заметить, по умолчанию свойство Text
содержит значение, совпадающее со значением имени компонента (Name)
- в данном случае “EditSource”. Свойство Text
Вы, естественно, можете редактировать как в режиме проектирования, так
и во время выполнения.

Текст, который должен быть
отображен в шести строках редактирования, передается процедуре WriteAll
как параметр. Чтобы передать параметр процедуре, просто напишите имя этой
процедуры и заключите передаваемый параметр (параметры) в скобки – вот
так:

WriteAll(EditSource.Text);

Заголовок этой процедуры
выглядит следующим образом:

procedure TForm1.WriteAll(NewString:
String);

где указано, что передаваемый
процедуре параметр NewString
должен иметь тип String.

Вспомним, что задача процедуры
WriteAll
состоит в копировании содержимого строки редактирования EditSource
в шесть других строк редактирования Edit1-Edit6.
Поэтому процедура должна выглядеть следующим образом:

procedure TForm1.WriteAll(NewString:
String);

begin

Edit1.Text := NewString;

Edit2.Text := NewString;

Edit3.Text := NewString;

Edit4.Text := NewString;

Edit5.Text := NewString;

Edit6.Text := NewString;

end;

Поскольку процедура WriteAll
не является откликом на какое-либо событие в Delphi, то ее нужно полностью
написать “вручную”. Простейший способ сделать это – скопировать заголовок
какой-либо уже имеющейся процедуры, исправить его, а затем дописать необходимый
код.

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

procedure TForm1.WriteAll(NewString:
String);

· Первая
часть – зарезервированное слово “procedure
”;
пятая
часть – концевая точка с запятой “
;”.
Обе эти части служат определенным синтаксическим целям, а именно: первая
информирует компилятор о том, что определен синтаксический блок “процедура”,
а вторая указывает на окончание заголовка (собственно говоря, все операторы
в Delphi должны заканчиваться точкой с запятой).

· Вторая
часть заголовка – слово “
TForm1”,
которое квалифицирует то обстоятельство, что данная процедура является
методом класса TForm1.

· Третья
часть заголовка – имя процедуры. Вы можете выбрать его любым, по вашему
усмотрению. В данном случае мы назвали процедуру “WriteAll”.

· Четвертая
часть заголовка – параметр. Параметр декларируется внутри скобок и, в свою
очередь, состоит из двух частей. Первая часть – имя параметра, вторая -
его тип. Эти части разделены двоеточием. Если Вы описываете в процедуре
более чем один параметр, нужно разделить их точкой с запятой, например:

procedure Example(Param1: String; Param2:
String);

После того как Вы создали
“вручную” заголовок процедуры, являющейся методом класса, Вы должны включить
его в декларацию класса, например, путем копирования (еще раз напомним,
что для методов, являющихся откликами на дельфийские события, данное включение
производится автоматически):

TForm1 = class(TForm)

Edit1: TEdit;

Edit2: TEdit;

Edit3: TEdit;

Edit4: TEdit;

Edit5: TEdit;

Edit6: TEdit;

EditSource: TEdit;

Button1: TButton;

procedure Button1Click(Sender: TObject);

procedure WriteAll(NewString: String);

end;

В данном месте нет необходимости
оставлять в заголовке метода слово “TForm1”, так как оно уже присутствует
в описании класса.

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

Листинг
-C
: Исходный код головного модуля программы PARAMS показывает, как
использовать строки редактирования и как передавать параметры.

Unit
Main;

interface

uses

WinTypes, WinProcs, Classes,

Graphics, Controls,

Printers, Forms, StdCtrls;

type

TForm1 = class(TForm)

Edit1: TEdit;

Edit2: TEdit;

Edit3: TEdit;

Edit4: TEdit;

Edit5: TEdit;

Edit6: TEdit;

EditSource: TEdit;

Button1: TButton;

procedure Button1Click(Sender:
TObject);

procedure WriteAll(NewString:
String);

end;

var

Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.WriteAll(NewString:
String);

begin

Edit1.Text := NewString;

Edit2.Text := NewString;

Edit3.Text := NewString;

Edit4.Text := NewString;

Edit5.Text := NewString;

Edit6.Text := NewString;

end;

procedure TForm1.Button1Click(Sender:
TObject);

begin

WriteAll(EditSource.Text);

end;

end.

При экспериментах с программой
PARAMS Вы можете попробовать изменить имена процедур и параметров. Однако,
следует помнить, что ряд слов в Delphi являются зарезервированными,
и употреблять их в идентификаторах (именах процедур, функций, переменных,
типов, констант) не разрешается – компилятор сразу же обнаружит ошибку.
К ним относятся такие слова, как “procedure”, “string”, “begin”, “end”
и т.п.; полный же список их приведен в on-line справочнике Delphi.

Не старайтесь запомнить сразу
все зарезервированные слова – компилятор “напомнит” Вам о неправильном
их использовании выдачей сообщения типа “Identifier expected.” (Ожидался
идентификатор, а обнаружено зарезервированное слово).

  1. Более
    сложные методы и управляющие элементы

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

В программе CONTROL1, рассмотренной
в начале урока, был сгенерирован метод, являющийся откликом на событие
OnClick
строки редактирования Edit1.
Аналогично, можно сгенерировать метод, являющийся реакцией на событие OnDblClick.
В программе CONTROL2, имеющейся на диске, расширен список находящихся на
форме компонентов и для многих из них определены события OnClick
и OnDblClick.
Для исследования Вы можете просто скопировать файлы проекта CONTROL1 в
новую директорию CONTROL2, изменить имя проекта на CONTROL2.DPR (в этом
файле после ключевого слова “program
также должно стоять название “CONTROL2”) и добавить компоненты Label,
GroupBox,
CheckBox,
RadioButton,
Button
на форму (эти компоненты находятся на страничке “Standard” Палитры Компонентов).
Ваша форма будет иметь примерно следующий вид – 8.

Заметим, что Вы должны “положить”
компонент GroupBox
на форму до того, как Вы добавите компоненты CheckBox
и RadioButton,
которые, в нашем примере, должны быть “внутри” группового элемента. Иначе,
объекты CheckBox1,
CheckBox2,
RadioButton1
и RadioButton2
будут “думать”, что их родителем является форма Form1
и при перемещении GroupBox1
по форме не будут перемещаться вместе с ней. Таким образом, во избежание
проблем, компонент, который должен быть “родителем” других компонент (Panel,
GroupBox,
Notebook,
StringGrid,
ScrollBox
и т.д.), нужно помещать на форму до помещения на нее его “детей”. Если
Вы все же забыли об этом и поместили “родителя” (например, GroupBox)
на форму после размещения на ней его “потомков” (например, CheckBox
и RadioButton)
- не отчаивайтесь! Отметьте все необходимые объекты и скопируйте (с удалением)
их в буфер обмена с помощью команд меню Edit|Cut. После этого отметьте
на форме нужный Вам объект (GroupBox1)
и выполните команду меню Edit|Paste. После этого все выделенные Вами ранее
объекты будут помещены на форму, и их “родителем” будет GroupBox1.
Описанный механизм является стандартным и может быть использован для всех
видимых компонент.

Выберите объект Label1.
Создайте для него метод, являющийся откликом на событие OnDblClick
(см. стр. *).
Введите в метод одну строчку, например:

procedure TForm1.Label1DblClick(Sender:
TObject);

begin

Edit1.Text := ‘Двойной щелчок на Label1′;

end;

Запустите программу на выполнение
и дважды щелкните мышкой на метке Label1.
Вы увидите, что строка редактирования изменится, и в ней появится текст
“Двойной щелчок на Label1”.

Теперь закройте приложение
и возвратитесь в режим проектирования. Добавьте обработчики событий OnClick
и OnDblClick
для каждого объекта, имеющегося на форме. Текст вашего головного модуля
будет выглядеть следующим образом:

Листинг -D:
Головной модуль программы CONTROL2.

Unit Main;

interface

uses

WinTypes, WinProcs, Classes,

Graphics, Controls, StdCtrls,

Printers, Menus, Forms;

type

TForm1 = class(TForm)

Label1: TLabel;

Edit1: TEdit;

Button1: TButton;

GroupBox1: TGroupBox;

CheckBox1: TCheckBox;

CheckBox2: TCheckBox;

RadioButton1: TRadioButton;

RadioButton2: TRadioButton;

procedure Edit1DblClick(Sender: TObject);

procedure Label1DblClick(Sender: TObject);

procedure CheckBox1Click(Sender: TObject);

procedure CheckBox2Click(Sender: TObject);

procedure RadioButton1Click(Sender: TObject);

procedure RadioButton2Click(Sender: TObject);

procedure Button1Click(Sender: TObject);

end;

var

Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.Edit1DblClick(Sender: TObject);

begin

Edit1.Text := ‘Двойной щелчок на Edit1′;

end;

procedure TForm1.Label1DblClick(Sender: TObject);

begin

Edit1.Text := ‘Двойной щелчок на Label1′;

end ;

procedure TForm1.CheckBox1Click(Sender: TObject);

begin

Edit1.Text := ‘Щелчок на CheckBox1′;

end;

procedure TForm1.CheckBox2Click(Sender: TObject);

begin

Edit1.Text := ‘Щелчок на CheckBox2′;

end;

procedure TForm1.RadioButton1Click(Sender: TObject);

begin

Edit1.Text := ‘Щелчок на RadioButton1′;

end;

procedure TForm1.RadioButton2Click(Sender: TObject);

begin

Edit1.Text := ‘Щелчок на Radiobutton2′;

end;

procedure TForm1.Button1Click(Sender: TObject);

begin

Edit1.Text := ‘Щелчок на Button1′;

end;

end.
Эта программа служит двум
целям:

  • Она показывает, как создавать
    процедуры (методы) и как “наполнять” их содержательной “начинкой”
  • Она демонстрирует технику работы
    с управляющими элементами Windows.
  1. Информация
    периода выполнения. Программа CONTROL3

Как Вы, наверное, заметили,
методы программы CONTROL2, являющиеся откликами на события OnClick
и OnDblClick,
во многом похожи друг на друга.

Открытость среды Delphi позволяет
получать и оперировать информацией особого рода, называемой информацией
периода выполнения (RTTI – run-time type
information). Эта информация организована в виде нескольких уровней.

Верхний уровеньRTTI
представлен как средство проверки и приведения типов с использованием ключевых
слов is
и as.

Ключевое слово is
дает программисту возможность определить, имеет ли данный объект требуемый
тип или является одним из наследников данного типа, например, таким образом:

if MyObject is TSomeObj
then

Имеется возможность использовать
RTTI и для процесса приведения объектного типа, используя ключевое слово
as:

if MyObject is TSomeObj then

(MyObject as TSomeObj).MyField:=…

что эквивалентно:

TSomeObj(MyObject).MyField:=…

Средний уровень
RTTI использует методы объектов и классов для подмены операций
as
и is
на этапе компиляции. В основном, все эти методы заложены в базовом классе
TObject,
от которого наследуются все классы библиотеки компонент VCL. Для любого
потомка TObject
доступны, в числе прочих, следующие информационные методы:

  • ClassName
    - возвращает имя класса, экземпляром которого является объект
  • ClassInfo
    - возвращает указатель на таблицу с RTTI, содержащей информацию о типе
    объекта, типе его родителя, а также о всех его публикуемых свойствах, методах
    и событиях
  • ClassParent
    - возвращает тип родителя объекта
  • ClassType
    - возвращает тип самого объекта
  • InheritsFrom
    - возвращает логическое значение, определяющее, является ли объект потомком
    указанного класса
  • InstanceSize
    - возвращает размер объекта в байтах.

Эти методы могут использоваться
в Вашем коде напрямую.

Нижний уровень
RTTI определяется в дельфийском модуле
TypInfo
и представляет особый интерес для разработчиков компонент. Через него можно
получить доступ к внутренним структурам Delphi, в том числе, к ресурсам
форм, инспектору объектов и т.п.

Итак, доступ к информации
периода выполнения в Delphi позволяет динамически получать как имя объекта,
находящегося на форме, так и название класса, которому он принадлежит (и
еще много другой полезной информации; но об этом – в дальнейших уроках).
Для этого используется свойство Name,
имеющееся у любого класса-наследника TComponent
(а таковыми являются все компоненты, входящие в дельфийскую библиотеку
VCL), и метод ClassName,
доступный для любого потомка класса базового TObject.
А, поскольку класс TComponent,
в свою очередь, является наследником класса TObject,
то он доступен для всех компонент из библиотеки VCL.

Вернувшись к нашим примерам,
мы можем заменить целую “кучу” методов двумя, реализующими события OnClick
и OnDblClick
для всех объектов сразу. Для этого можно скопировать все файлы из CONTROL2
в новый директорий CONTROL3 или использовать для работы уже имеющуюся на
диске программу. Создадим стандартным образом методы ControlDblClick
и ControlClick
для какого-либо объекта (например, для Label1).
Введем в них следующие строки:

procedure TForm1.ControlDblClick(Sender:
TObject);

begin


Edit1.Text
:= ‘Двойной щелчок на ‘ +

(Sender as TComponent).Name +

‘ (класс ‘ + Sender.ClassName + ‘)’;


end;

procedure TForm1.ControlClick(Sender: TObject);

begin


Edit1.Text
:= ‘Щелчок на ‘ +

(Sender as TComponent).Name +


‘ (класс ‘
+ Sender.ClassName + ‘)’;

end;

Теперь назначим данные методы
всем событиям OnClick
и OnDblClick,
имеющимся у расположенных на форме объектов. Мы видим, что размер программы
существенно сократился, а функциональность ее значительно выросла. В режиме
выполнения после, например, щелчка на объекте CheckBox1
приложение будет иметь вид, изображенный на 8.

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

Заключение

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

Комментариев Нет.

Написать Ответ

Вы должны войти чтобы оставить комментарий.