ВВЕДЕНИЕ В OBJECT PASCAL


В этой и последующих главах второй части книги мы будем изучать основной инструмент Delphi - язык Object Pascal. Назначение этой главы - предоставить вам возможность неформального знакомства с основными свойствами языка без точного описания и углубленного изучения его конструкций.
УЧЕБНАЯ ПРОГРАММА
При описании свойств языка мне понадобится иллюстрировать их небольшими примерами. В таких примерах чаще всего реализуются простые действия по вводу некоторых данных, их преобразованию и выводу результатов на экран. Для реализации этих действий создадим форму, которая будет содержать все необходимые для учебных примеров интерфейсные элементы. Чтобы эта форма была доступна в любой учебной программе, мы поместим ее в так называемый репозиторий Delphi - архив, в котором сохраняются заготовки для новых программ. Замечу, что в версии 1 нет репозитория. Тем не менее полезно и в этом случае создать учебную форму: чтобы избавить себя от повторения одних и тех же действий при реализации разных примеров. Сохраните ее в файле с именем Example, например, а при создании новой программы свяжите ее с проектом (опция File | Add) и сразу же сохраните под другим именем (File | Save As).
Вид формы для учебной программы показан на На форме размещена панель (трапе!), две кнопки (TBitBtn), строка ввода (TEdit), метка (TLabel) и многострочный редактор (тмето). Панель понадобилась для того, чтобы размещенные на ней кнопки, строка ввода и метка всегда располагались в нижней части окна, даже если окно распахнуто на весь экран. Левая кнопка ок служит для сообщения программе о том, что в строке ввода подготовлен текст. Обработчик события onciick этой кнопки будет тем самым местом программы, куда мы будем помещать учебные фрагменты. Правая кнопка close служит для завершения работы программы. Ее функции аналогичны функциям системной кнопки закрытия окна, и поэтому ее можно было бы и не размещать на форме. Однако я предпочитаю использовать крупную, бросающуюся в глаза кнопку, чтобы даже неопытный пользователь сразу увидел интерфейсный элемент, с помощью которого он сможет прекратить работу с программой. Метка располагается над строкой ввода и пока не видна на экране. Она предназначена для размещения коротких сообщений, которые будет формировать программа. Для вывода многострочных сообщений служит редактор TMеmо, занимающий все остальное место окна.
Конструирование формы
Вы можете самостоятельно сконструировать форму для учебной программы, руководствуясь приведенным выше описанием размещенных на ней компонентов. Для облегчения этого процесса ниже для каждого компонента указаны свойства, значения которых отличаются от умалчиваемых. Компоненты перечислены в порядке их размещения, т. е. вначале подготавливаются свойства формы, потом на форму помещается панель, на нее помещаются кнопки и строка ввода, а метка и многострочный редактор - на свободное место формы над панелью.
Размеры компонентов установлены с учетом разрешения экрана 800х600. Для другого разрешения эти размеры, возможно, потребуется скорректировать.
Форма


Свойство

Значение

Caption
Height
Name
Position
Width

Учебная программа
375
fmExample
poScreenCenter
544

 
Панель (компонент panel на странице Standard). Кладется на любое свободное место формы.


Свойство

Значение

Align
BevelOuter Caption
Height

AlBottom
BvNone Удалить
84

 
Кнопка OK (компонент BitBtn на странице Additional). Кладется на любое свободное место панели.


Свойство

Значение

Kind

bkOk

Left

32

Name

bbRun

Тор

48

 
Кнопка close (компонент BitBtn на странице Additional). Кладется на любое свободное место панели.


Свойство

Значение

Kind

bkClose

Left

128

Name

BbClose

Тор

48

 
Строка ввода (компонент Edit на странице standard). Кладется на любое свободное место панели.


Свойство

Значение

Name

edinput

Left

128

Text

Удалить

Top

16

Width

289

Метка (компонент Label на странице Standard). Кладется на любое свободное место формы.


Свойство

Значение

Align
Caption
Name

alBottom
Удалить
IbOutput

 
Многострочный редактор (компонент Memo на странице Standard). Кладется на любое свободное место формы.


Свойство

Значение

Align

alClient

Lines

Удалить

Name

mmOutput

ScrollBars

ssBoth

Wordwrap

False

Следует прокомментировать сделанные нами изменения умалчиваемых значений свойств.
Размеры формы Height (Высота) и Width (Ширина) совпадают с умалчиваемыми. Они выбраны так, чтобы форма не казалась слишком маленькой или слишком большой на экранах с разным разрешением - они оптимальны для типичного на сегодня разрешения 800х600. Свойство Position управляет размещением формы относительно границ экрана. Умалчиваемое значение poDesigned потребует разместить форму так, как она была размещена на этапе конструирования, рекомендуемое значение poScreencenter - симметрично по центру экрана.
Свойство Align указывает способ выравнивания размещаемого компонента относительно того контейнера, в котором он размещается. Контейнером называется компонент, предназначенный для размещения в нем других компонентов. Пустая форма представляет собой контейнер, в который помещаются другие компоненты. Таким же контейнером является компонент panel. Мы разместили на форме панель и в ее свойство Align установили значение alBottom (Внизу). После установки этого значения компонент (в данном случае - панель) прижимается к нижней границе формы и растягивается по всей ее длине. Теперь панель и все размещенные на ней компоненты будут примыкать к нижнему краю окна, даже если окно распахивается на весь экран. Если бы мы разместили строку ввода и кнопки не на панели, а непосредственно на форме, они не имели бы свойства перемещения и оставались бы на своих местах при изменении размеров окна [ На самом деле это не совсем так. Компонент действительно не будет перемещаться при стандартных (умалчиваемых) значениях его свойства Anchors. Подробнее об этом см. п. 16.4. ]. В результате значительная часть полностью распахнутого окна осталась бы пустой и не использовалась.
Свойство caption (Заголовок) присуще всем видимым элементам. Для панели оно определяет текст, который размещается в ее центре. Поскольку мы не намерены размещать на панели никаких текстовых сообщений, это свойство у нее следует очистить.
Чтобы панель и расположенная над ней метка воспринимались как единое целое, в свойстве BevelOuter (Внешняя кромка) панели установлено значение bvNone.
Свойства Left (Слева), тор (Сверху) и width (Ширина) определяют положение левого верхнего угла компонента относительно такого же угла своего контейнера и его (компонента) ширину. Указанные в списке значения этих свойств, для строки ввода обеспечат симметричное по горизонтали расположение строки относительно сторон не распахнутого окна (если, разумеется, вы установили рекомендуемую ширину формы 544). К сожалению, симметрия будет нарушена, если окно распахнется. В Delphi есть средства изменения значений указанных свойств непосредственно в работающей программе. Создав обработчик события ОnResize (По изменению размера) для формы, мы при желании могли бы научить программу реагировать на изменение размеров окна и соответствующим образом изменять значение свойства Left для строки ввода.
Свойство Name (Имя) определяет имя, под которым компонент будет известен программе. Я настоятельно рекомендую вам давать компонентам, на которые ссылается код программы, имена “со смыслом” вместо однотипных имен, которые “придумывает” Delphi. Более того, по принятому в современной практике программирования стилю именам обычно предшествует двухбуквенный префикс. Заложенная в префиксе мнемоника служит напоминанием программисту о типе поименованного компонента или его свойства. Например, все возможные значения свойства Align имеют стандартный для Delphi префикс а1 (от Align), за которым следует вполне понятное английское слово: alBottom, alTop, alLeft и т. д. Строка ввода будет непременным участником кода большинства учебных программ, вот почему я предлагаю назвать этот компонент именем edInput: префикс ed - это сокращение английского названия типа компонента Edit, слово Input означает ввод данных в программу. Такими же осмысленными являются предлагаемые имена для метки - от Label, output - вывод программы), многострочного редактора (mm - от Memo), кнопки OK (bb - ОТ BitBtn, Run - пуск программы) и кнопки close. Панель вряд ли будет упоминаться в программном коде, который вы будете писать, поэтому для нее можно оставить созданное Delphi умалчиваемое имя panel1.
Свойство Text (Текст) у компонента Edit определяет текст, который будет содержать строка ввода в момент появления на экране. Следует очистить это свойство, чтобы начальный текст не мешал вводу данных для программы. Точно так же следует очистить свойство Caption у метки и Lines у многострочного редактора. Чтобы очистить свойство mmOutput. Lines, щелкните по этому свойству в окне Инспектора объектов и вызовите диалоговое окно изменения свойства. Затем удалите умалчиваемый текст Memo1 (или mmoutput, если к этому моменту вы уже дали компоненту рекомендуемое имя) и закройте окно кнопкой OK.
Свойство ScrollBars у компонента mmOutput имеет значение ssBoth (Оба). Такое значение заставит Delphi поместить в редактор обе полосы прокрутки - вертикальную и горизонтальную. Наличие полос поможет вам увидеть текст, отсекаемый границами компонента. В то же время для свойства wordwrap (Перенос слов) советую установить значение False, чтобы отказаться от переноса слов на другую строку редактора в длинных текстовых сообщениях. Для этого компонента свойство Align имеет значение alciient, что потребует от компонента занять всю оставшуюся незаполненной часть формы независимо от размеров окна.
Для компонентов BitBtn свойство Kind (Сорт) определяет типовые функции, которые реализует кнопка в диалоговых окнах. Значение bkCiose определит типовую пиктограмму и надпись close, ко-торые Delphi разместит на кнопке, а также типовую функцию закрытия окна, которая будет связана с этой кнопкой. В результате без малейших усилий с нашей стороны мы получили кнопку, которая завершает работу программы. Значение bkOK заставит кнопку BitBtn закрывать диалоговое окно с результатом тгок. Поскольку наша форма не является диалоговым окном, кнопка ок не будет выполнять эту свою функцию: мы использовали значение bkOK только для того, чтобы кнопка получила нужную пиктограмму и надпись.
Перенос формы в архив
После указанных выше изменений сохраните форму в файле с именем Example в каталоге архива Delphi. Этот каталог имеет имя Objrepos и размещается в каталоге размещения Delphi (по умолчанию - c:\Program Files\Borland\Delphi6). Архив (репозиторий)
Delphi служит для накопления типовых форм и проектов. Использование типовых заготовок стандартизует вид окон и способствует формированию собственного для программиста стиля оформления своих программных проектов.
Перенос формы в каталог Objrepos еще не обеспечивает включение этой формы в архив. Чтобы вызвать диалоговое окно регистрации формы в архиве, щелкните по форме правой кнопкой мыши и в появившемся вспомогательном меню выберите продолжение Add то Repository (см
Не советую пользоваться опцией меню Project | Add то Repositiry, т. к. в этом случае в репозиторий будет добавлен проект, а не форма. Проекты из репозитория копируются целиком вместе с многочисленными родительскими классами, что замедляет время создания нового проекта и приводит к неоправданным затратам дисковой памяти.
В строке Title напишите имя формы fmExample, В Строке Description — пояснение, например, прототип главной формы для учебной программы, раскройте список page и выберите в нем Forms. Если хотите, укажите в строке Author свою фамилию и закройте окно регистрации кнопкой ок. Теперь форма зарегистрирована, и вы в любой момент сможете выбрать ее с помощью опции File | New | other главного меню Delphi. Однако я предлагаю не успокаиваться на этом и определить нашу форму как главную, тогда Delphi при выборе опции File | New | Application будет именно ее показывать вместо пустой типовой формы. Для этого с помощью опции Tools | Repository главного меню вызовите диалоговое окно, показанное на
В списке pages этого окна щелкните по строке Forms и разыщите в самом конце списка объектов objects нашу форму fmExampie. Щелкните по ней, установите флажок в переключателе Main Form (Главная форма) и закройте окно клавишей ок. Когда нам в дальнейшем понадобится создавать проекты, основанные на стандартных пустых формах, вам потребуется вновь вызвать опцию Tools | Repository и убрать флажок в переключателе Main Form.
Чтобы убедиться в правильности ваших действий, закройте проект, ответив нажатием на кнопку No в ответ на предложение Delphi сохранить файл проекта, и выберите File | New | Application-на экране должна появится уже знакомая нам форма учебной программы.
СТРУКТУРА ПРОГРАММ DELPHI
Любая программа в Delphi состоит из файла проекта (файл с расширением dpr) и одного или нескольких модулей (файлы с расширениями pas). Каждый из таких файлов описывает программную единицу Object Pascal.
Структура проекта
Файл проекта представляет собой программу, написанную на языке Object Pascal и предназначенную для обработки компилятором. Эта программа автоматически создается Delphi и содержит лишь несколько строк. Чтобы увидеть их, запустите Delphi и щелкните по опции Project | View Source главного меню [ В предыдущих версиях Delphi для просмотра кода проекта используйте опцию View | project Source. ]. Delphi покажет окно кода с закладкой Project1, содержащее такой текст:
program Projecti;
uses
Forms, Unit1 in 'Unit1.pas' {fmExample};
{$R *.RES}
begin
Application.Initialize;
Application.CreateForm(TfmExample, fmExample);
Application.Run;
end.
В окне кода жирным шрифтом выделяются так называемые зарезервированные слова, а курсивом - комментарии (так же выделяются зарезервированные слова и комментарии в книге). Как видим, текст программы начинается зарезервированным словом program и заканчивается словом end с точкой за ним. Замечу, что сочетание end со следующей за ней точкой называется терминатором программной единицы: как только в тексте программы встретится такой терминатор, компилятор прекращает анализ программы и игнорирует оставшуюся часть текста.
Зарезервированные слова играют важную роль в Object Pascal, придавая программе в целом свойство текста, написанного на почти естественном английском языке. Каждое зарезервированное слово (а их в Object Pascal несколько десятков) несет в себе условное сообщение для компилятора, который анализирует текст программы так же, как читаем его и мы: слева направо и сверху вниз.
Комментарии, наоборот, ничего не значат для компилятора, и он их игнорирует. Комментарии важны для программиста, который с их помощью поясняет те или иные места программы. Наличие комментариев в тексте программы делает ее понятнее и позволяет легко вспомнить особенности реализации программы, которую вы написали несколько лет назад. В Object Pascal комментарием считается любая последовательность символов, заключенная в фигурные скобки. В приведенном выше тексте таких комментариев два, но строка
{$R *.RES}
на самом деле не является комментарием. Этот специальным образом написанный фрагмент кода называется директивой компилятора (в нашем случае - указание компилятору на необходимость подключения к программе так называемого файла ресурсов). Директивы начинаются символом $, который стоит сразу за открывающей фигурной скобкой.
Поскольку речь зашла о комментариях, замечу, что в Object Pascal в качестве ограничителей комментария могут также использоваться пары символов (*, *) и //. Скобки (*...*) используются подобно фигурным скобкам т. е. комментарием считается находящийся в них фрагмент текста, а символы // указывают компилятору, что комментарий располагается за ними и продолжается до конца текущей строки:
{Это комментарий}
(*Это тоже комментарий*)
//Все символы до конца этой строки составляют комментарий
Слово Program со следующим за ним именем программы и точкой с запятой образуют заголовок программы. За заголовком следует раздел описаний, в котором программист (или Delphi) описывает используемые в программе идентификаторы. Идентификаторы обозначают элементы программы, такие как типы, переменные, процедуры, функции (об элементах программы мы поговорим чуть позже). Здесь же с помощью предложения, которое начинается зарезервированным словом uses (использовать) программист сообщает компилятору о тех фрагментах программы (модулях), которые необходимо рассматривать как неотъемлемые составные части программы и которые располагаются в других файлах. Строки
uses
Forms, Unit1 in 'Unitl.pas' {fmExample};
указывают, что помимо файла проекта в программе должны использоваться модули Forms И Unit1. модуль Forms является стандартным (т. е. уже известным Delphi), а модуль Unit1 - новым, ранее неизвестным, и Delphi в этом случае указывает также имя файла с текстом модуля (in 'uniti.pas') и имя связанного с модулем файла описания формы {fmExample}.
Собственно тело программы начинается со слова begin (начать) и ограничивается терминатором end с точкой. Тело состоит из нескольких операторов языка Object Pascal. В каждом операторе реализуется некоторое действие - изменение значения переменной, анализ результата вычисления, обращение к подпрограмме и т. п. В теле нашей программы - три исполняемых оператора:
Application.Initialize;
Application.CreateForm(TfmExample, fmExample);
Application.Run;
Каждый из них реализует обращение к одному из методов объекта Application. Я вынужден забежать вперед и хотя бы кратко пояснить только что введенные термины, которые определяют важные для Object Pascal понятия. Объектом называется специальным образом оформленный фрагмент программы, заключающий в себе данные и подпрограммы для их обработки. Данные называются полями объекта, а подпрограммы - его методами. Объект в целом предназначен для решения какой-либо конкретной задачи и воспринимается в программе как неделимое целое (иными словами, нельзя из объекта “выдернуть” отдельное поле или метод). Объекты играют чрезвычайно важную роль в современных языках программирования. Они придуманы для того, чтобы увеличить производительность труда программиста и одновременно повысить качество разрабатываемых им программ. Два главных свойства объекта - функциональность и неделимость - делают его самостоятельной или даже самодостаточной частью программы и позволяют легко переносить объект из одной программы в другую. Разработчики Delphi придумали для нас с вами сотни объектов, которые можно рассматривать как кирпичики, из которых программист строит многоэтажное здание программы. Такой принцип построения программ называется объектно-ориентированным программированием (ООП). В объекте Application собраны данные и подпрограммы, необходимые для нормального функционирования Windows-программы в целом. Delphi автоматически создает объект-программу Application для каждого нового проекта. Строка
Application.Initialize;
означает обращение к методу Initialize объекта Application. Прочитав эту строку, компилятор создаст код, который заставит процессор перейти к выполнению некоторого фрагмента программы, написанного для нас разработчиками Delphi. После выполнения этого фрагмента (программисты говорят: после выхода из подпрограммы) управление процессором перейдет к следующей строке программы, в которой вызывается метод CreateForm и т. д.
Структура модуля
Модули - это программные единицы, предназначенные для размещений фрагментов программ. С помощью содержащегося в них программного кода реализуется вся поведенческая сторона программы. Любой модуль имеет следующую структуру [ Более точное описание структуры модуля приводится в п. 12.1. ]: заголовок секция интерфейсных объявлений секция реализации терминатор Заголовок открывается зарезервированным словом Unit за которым следует имя модуля и точка с запятой. Секция интерфейсных объявлений открывается зарезервированным словом Interface, a секция реализации - словом implementation. Терминатором модуля, как и терминатором программы, является end с точкой. Следующий фрагмент программы является синтаксически правильным вариантом модуля:
unit Unit1;
interface
// Секция интерфейсных объявлений
implementation
// Секция реализации
end.
В секции интерфейсных объявлений описываются программные элементы (типы, классы, процедуры и функции), которые будут “видны” другим программным модулям, а в секции реализации раскрывается механизм работы этих элементов. Разделение модуля на две секции обеспечивает удобный механизм обмена алгоритмами между отдельными частями одной программы. Он также реализует средство обмена программными разработками между отдельными программистами. Получив откомпилированный “посторонний” модуль, программист получает доступ только к его интерфейсной части, в которой, как уже говорилось, содержатся объявления элементов. Детали реализации объявленных процедур, функций, классов скрыты в секции реализации и недоступны другим модулям.
Щелкните по закладке Unit1 окна кода, и вы увидите такой текст:
  unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls,
Forms, Dialogs, StdCtrls, Buttons, ExtCtrls;
type
TfmExample = class (TForm)
Panel1: TPanel;
bbRun: TBitBtn;
bbClose: TBitBtn;
edinput: TEdit;
IbOutput: TLabel;
mmOutput: TMemo;
private
{ Private declarations } public
{ Public declarations } end;
var
fmExample: TfmExample;
implementation
$R *.DFM}
end.
Весь этот текст сформирован Delphi, но в отличие от файла проекта программист может его изменять, придавая программе нужную функциональность. В интерфейсной секции описан один тип (класс - fmExample) и один объект (переменная fmExample).
Вот описание класса:
type
TfmExample = class(TForm)
Panell: TPanel;
bbRun: TBitBtn;
bbClose: TBitBtn;
edinput: TEdit;
IbOutput: TLabel;
mmOutput: TMemo;
private
{ Private declarations } public
{ Public declarations } end;
Как мы увидим дальше, классы служат основным инструментом реализации мощных возможностей Delphi. Класс является образцом, по которому создаются объекты, и наоборот, объект - это экземпляр реализации класса. Образцы для создания элементов программы в Object Pascal называются типами, таким образом, класс TfmExamplel -это тип. Перед его объявлением стоит зарезервированное слово type (тип), извещающее компилятор о начале раздела описания типов.
Стандартный класс TForm реализует все нужное для создания и функционирования пустого Windows-окна. Класс TfmExamplel порожден от этого класса, о чем свидетельствует строка
TfmExample = class (TForm)
в которой за зарезервированным словом class в скобках указывается имя родительского класса. Термин “порожден” означает, что класс TfmExample унаследовал все возможности родительского класса TForm и добавил к ним собственные в виде дополнительных компонентов, которые, как вы помните, мы вставили в форму fmExample. Перечень вставленных нами компонентов и составляет значительную часть описания класса.
Свойство наследования классами-потомками всех свойств родительского класса и обогащения их новыми возможностями является одним из фундаментальных принципов объектно-ориентированного программирования. От наследника может быть порожден новый наследник, который внесет свою лепту в виде дополнительных программных заготовок и т. д. В результате создается ветвящаяся иерархия классов, на вершине которой располагается самый простой класс TObject (все остальные классы в Delphi порождены от этого единственного прародителя), а на самой нижней ступени иерархии - мощные классы-потомки, которым по плечу решение любых проблем.
Объект fmExampie формально относится к элементам программы, которые называются переменными. Вот почему перед объявлением объекта стоит зарезервированное слово var (от англ. variables - переменные).
Примечание
Текст модуля доступен как Delphi ,так и программисту. Delphi автоматически вставляет в текст модуля описание любого добавленного к? форме компонента, а также создает заготовки для обработчиков событии; программист может добавлять свои методы в ранее объявлённые классыйнаполвять обработчики событий конкретным .содержа,нием, вставлять собственные переменные, типы, константы и т. д. Совместное с Delphi владение текстом модуля будет вполне успешным, если программист будет соблюдать простое правило , он не должен удалять или изменять строки которые вставлены не им, а Delphi.
Элементы программы
Элементы программы - это минимальные неделимые ее части, еще несущие в себе определенную значимость для компилятора. К элементам относятся:

  • зарезервированные слова;
  • идентификаторы;
  • типы;
  • константы;
  • переменные;
  • метки;
  • подпрограммы;
  • комментарии.

Зарезервированные слова это английские слова, указывающие компилятору на необходимость выполнения определенных действий. Зарезервированные слова не могут использоваться в программе ни для каких иных целей кроме тех, для которых они предназначены. Например, зарезервированное слово begin означает для компилятора начало составного оператора. Программист не может создать в программе переменную с именем begin, константу begin, метку begin или вообще какой бы то ни было другой элемент программы с именем begin.
Идентификаторы - это слова, которыми программист обозначает любой другой элемент программы, кроме зарезервированного слова, идентификатора или комментария. Идентификаторы в Object Pascal могут состоять из латинских букв, арабских цифр и знака подчеркивания. Никакие другие символы или специальные знаки не могут входить в идентификатор. Из этого простого правила следует, что идентификаторы не могут состоять из нескольких слов (нельзя использовать пробел) или включать в себя символы кириллицы (русского алфавита).
Типы - это специальные конструкции языка, которые рассматриваются компилятором как образцы для создания других элементов программы, таких как переменные, константы и функции. Любой тип определяет две важные для компилятора вещи: объем памяти, выделяемый для размещения элемента (константы, переменной или результата, возвращаемого функцией), и набор допустимых действий, которые программист может совершать над элементами данного типа. Замечу, что любой определяемый программистом идентификатор должен быть описан в разделе описаний (перед началом исполняемых операторов). Это означает, что компилятор должен знать тот тип (образец), по которому создается определяемый идентификатором элемент.
Константы определяют области памяти, которые не могут изменять своего значения в ходе работы программы. Как и любые другие элементы программы, константы могут иметь свои собственные имена. Объявлению имен констант должно предшествовать зарезервированное слово const (от англ. constants - константы). Например, мы можем определить константы const
Kbyte = 1024;
Mbyte = Kbyte*Kbyte;
Gbyte = 1024*Mbyte;
чтобы вместо длинных чисел
1048576 (1024*1024) и 1073741824
(1024*1024*1024) писать, соответственно, Mbyte и Gbyte. Тип константы определяется способом ее записи и легко распознается компилятором в тексте программы, поэтому программист может не использовать именованные константы (т. е. не объявлять их в программе явно).
Переменные связаны с изменяемыми областями памяти, т. е. с такими ее участками, содержимое которых будет меняться в ходе работы программы. В отличие от констант переменные всегда объявляются в программе. Для этого после идентификатора переменной ставится двоеточие и имя типа, по образу которого должна строиться переменная. Разделу объявления переменной (переменных) должно предшествовать слово var. Например:
var
inValue: Integer;
byValue: Byte;
Здесь идентификатор inValue объявляется как переменная типа integer, а идентификатор byValue - как переменная типа Byte. Стандартный (т. е. заранее определенный в Object Pascal) тип integer определяет четырехбайтный участок памяти, содержимое которого рассматривается как целое число в диапазоне от -2 147 483 648 до+2 147 483 647, а стандартный тип Byte - участок памяти длиной 1 байт, в котором размещается беззнаковое целое число в диапазоне от 0 до 255 4 .[ Все приводимые в книге сведения относительно диапазона возможных значений и объема памяти стандартных типов относятся к Delphi 32. Для 16-разрядной версии 1 эти величины имеют другие значения, например, тип Integer в версии 1 занимает 2 банта и имеет диапазон значении от -32 768 до+32 767. ]
Метки - это имена операторов программы. Метки используются очень редко и только для того, чтобы программист смог указать компилятору, какой оператор программы должен выполнятся следующим. Метки, как и переменные, всегда объявляются в программе. Разделу объявлений меток предшествует зарезервированное сло-во label (метка). Например:
label
Loop;
begin
Goto Loop;
// Программист требует передать управление
// оператору, помеченному меткой Loop. .....
// Эти операторы будут пропущены
Loор:
// Оператору, идущему за этой меткой,
.....
// будет передано управление
end;
Подпрограммы - это специальным образом оформленные фрагменты программы. Замечательной особенностью подпрограмм является их значительная независимость от остального текста программы. Говорят, что свойства подпрограммы локализуются в ее теле. Это означает, что, если программист что-либо изменит в подпрограмме, ему, как правило, не понадобится в связи с этим изменять что-либо вне подпрограммы. Таким образом, подпрограммы являются средством структурирования программ, т. е. расчленения программ на ряд во многом независимых фрагментов. Структурирование неизбежно для крупных программных проектов, поэтому подпрограммы используются в Delphi-программах очень часто.
В Object Pascal есть два сорта подпрограмм: процедуры и функции. Функция отличается от процедуры только тем, что ее идентификатор можно наряду с константами и переменными использовать в выражениях, т. к. функция имеет выходной результат определенного типа. Если, например, определена функция
Function MyFunction: Integer;
и переменная var
X: Integer;
то возможен такой оператор присваивания:
Х := 2*MyFunction-l;
Имя процедуры нельзя использовать в выражении, т. к. процедура не имеет связанного с нею результата:
Procedure MyProcedure;

X := 2*MyProcedure-l; // Ошибка!
ТИПЫ
Типы в Object Pascal играют огромную роль. Связано это с тем, что лежащий в его основе язык Pascal был специально придуман как средство обучения студентов программированию. Поскольку начинающий программист легко может допустить ошибку или неточно описать свои действия, компилятор Pascal должен был иметь средства контроля за действиями программиста, чтобы вовремя предостеречь его от последствий неверных действий. Первоначально типы как раз и предназначались для того, чтобы программист явно указывал компилятору, какого размера память нужна ему в программе и что он собирается делать с этой памятью. Практика применения типов показала их высокую эффективность для защиты программы от случайных ошибок, так что практически все современные языки программирования в той или иной степени реализуют механизм типов. В Object Pascal значение типов возросло в еще большей степени, т. к. с их помощью определяются классы - основной инструмент программиста.

Строковый и символьный типы


Свое знакомство с типами мы начнем со строкового типа String. Этот тип определяет участок памяти переменной длины, каждый байт которого содержит один символ. Для символов в Object Pascal используется тип Char, таким образом, String - это цепочка следующих друг за другом символов Char. Каждый символ в String пронумерован, причем первый символ имеет номер 1. Программист может обращаться к любому символу строки, указывая его порядковый номер в квадратных скобках сразу за именем переменной:
var // Начало раздела описания переменных
S: String;
// Объявление переменной строкового типа
begin
// Начало раздела исполняемых операторов
S := ' Строка символов';
// Переменная S содержит
// значение ”Строка символов”
S[6] := 'и'; // Теперь переменная содержит значение
// ”Строки символов”
end;
// Конец раздела исполняемых операторов
Наличие комментариев избавляет меня от необходимости подробного описания назначения каждой строки текста. Напомню, что программист обязан объявить любой вводимый им идентификатор. Идентификатор s неизвестен Delphi - он введен нами для переменной строкового типа. После его объявления в разделе переменных Delphi выделит для него начальную область памяти минимальной длины и будет контролировать использование этого идентификатора в разделе исполняемых операторов. Например, если в этом разделе встретится выражение
2*S-1
компилятор сразу забьет тревогу, так как строка не может быть участником математических вычислений: она предназначена для хранения символов, а не чисел.
В первом операторе присваивания в переменную s будет помещено значение строковой константы строка символов'. Строковые константы содержат произвольные символы, заключенные в обрамляющие апострофы, причем сами апострофы не входят в значение константы, поэтому после присваивания переменная примет значение Строка символов без апострофов (если понадобится включить в текстовую константу апостроф, он удваивается: ' символ ' ' - апостроф'). После первого присваивания s будет занимать участок памяти длиной 15 байт - по одному байту на каждый символ значения[ На самом деле переменная строкового типа всегда имеет длину 4 байта, которые используются для указания на область памяти, в которой помещается сама строка символов. Подробнее о механизме использования памяти строковыми переменными см. п. 6.3.1. ]. Переменность размера области памяти, выделяемой для размещения строки символов, - характерная особенность типа string. Если бы, например, во втором операторе мы обратились не к 6-му по счету символу, а ко всей строке в целом:
S := 'и';
эта переменная стала бы занимать 1 байт, а следующие за ним 14 байтов оказались бы свободными. Длина строковой переменной в программе меняется автоматически при каждом присваивании переменной нового значения и может составлять от 0 до 2 Гбайт[ Для версии Delphi 1 тип String соответствует “короткой” строке, длина которой не может превышать 255 байт. ] (1 Гигабайт (Гбайт) соответствует константе Gbyte на стр. 84). Над строковым типом определена операция сцепления (+):
S := 'Object'+' Pascal';// S содержит “Object Pascal”
 
Кроме того, строки можно сравнивать с помощью таких операций отношения:


Операция

Смысл

=

Равно

<>

Не равно

>

Больше

>=

Больше или равно

<

Меньше

<=

Меньше или равно

Примечание
Символы <>, <= и >= пишутся слитно, их нельзя разделять пробелами иди комментариями.
Результат применения операции сравнения к двум строкам имеет логический тип, который характеризуется двумя возможными значениям: True (Истина; читается тру) и False (Ложь; читается фоле). Строки сравниваются побайтно, слева направо; каждая пара символов сравнивается в соответствии с их внутренней кодировкой (см. гл. 7).
Все остальные действия над строками осуществляются с помощью нескольких стандартных для Delphi подпрограмм, описанных в гл.7.
Учебная программа COPY.TXT
Создадим программу, в которой текст из строки ввода edinput будет копироваться без изменений в метку lboutput и редактор mmoutput. Для этого загрузите Delphi и выберите опцию File | New | Application [ Как уже говорилось в гл. 2, имеет смысл для каждой учебной программы создавать свой подкаталог и размещать в нем все связанные с программой файлы. Если вы еще не сделали этого, минимизируйте Delphi и создайте с помощью Проводника подкаталог COPYTXT в каталоге для ваших учебных программ. В дальнейшем я не буду напоминать вам о необходимости создания подкаталогов, однако помните, что, если вы не будете этого делать, очень скоро ваш учебный каталог станет представлять собой хаотическое нагромождение никак не связанных друг с другом файлов. ].
Чтобы сообщить программе о том, что в строке ввода edinput подготовлен текст, пользователь должен щелкнуть по кнопке bbRun, поэтому все необходимые действия мы сосредоточим в обработчике события onciick этой кнопки. Дважды щелкните по кнопке bbRun в окне формы, чтобы Delphi автоматически подготовила для вас заголовок обработчика события, и отредактируйте его следующим образом: 
procedure TfmExample.bbRunClick(Sender: TObject);
begin
lbOutput.Caption := edInput.Text;
// ПовторяемтекствметкеmmOutput.Lines.Add(edInput.Text);
// и в многострочном редакторе
edInput.Text := '';
// Очищаем строку ввода edInput.SetFocus;
// Передаем ей фокус ввода
end;
Нажмите F9 для прогона программы, сохраните модуль под именем CopyTxtU.pas, а проект в целом - под именем copyTxt.dpr, и вы увидите окно, показанное на
  Комментарий к программе
Вводимый текст хранится в свойстве Text компонента edInput. После выполнения первого оператора присваивания он будет перенесен в свойство caption компонента IbOutput и тут же появится на экране над строкой ввода.
Многострочньш редактор mmOutput способен сохранять и отображать на экране множество строк. Все они содержатся в его свойстве Lines, относящемуся к классу TStringList (подробнее об этом классе см. п. 12.1). Метод Add класса TStringList добавляет новую строку к имеющемуся в Lines набору строк. Добавленная с помощью второго оператора строка тут же отображается на экране. С помощью оператора
edInput.Text := ' ' ;
строка ввода очищается и подготавливается к вводу нового текста. Двойной апостроф в правой части оператора указывает “пустую” строку или, что то же, строку нулевой длины. Завершает обработчик оператор
edinput.SetFocus ;
с помощью которого строка edinput получает фокус ввода. Термином “фокус ввода” в Delphi фактически обозначается клавиатура”* “Получить фокус ввода” означает связать указанный компонент с клавиатурой. В окне программы может быть несколько компонентов, способных принимать и обрабатывать клавиатурный ввод (в нашей программе таких компонентов четыре: редактор mmoutput, строка edinput и кнопки bbRun и bbciose). Каждый из таких компонентов имеет метод SetFocus, с помощью которого программа может передать компоненту контроль над клавиатурой. Чтобы оценить действия, реализуемые оператором edinput. SetFocus, поставьте в самом начале оператора признак комментария (символы “//”), сделайте новый прогон программы и введите с ее помощью хотя бы 2-3 строки.
Замечу, что в момент появления окна программы на экране строка edinput не имеет фокуса ввода, что затрудняет ввод первой строки. Попробуйте самостоятельно создать обработчик события опАс-tivate для формы fmExampie и в нем установить фокус ввода для строки edinput. (Подсказка: раскройте список выбора в верхней части окна Инспектора объектов, выберите в нем компонент fmExampie и дважды щелкните по правой колонке свойства OnActivate на странице Events этого окна.)
Целые типы
Целые типы используются для хранения и преобразования целых чисел. В Object Pascal предусмотрено несколько целочисленных типов, отличающихся диапазоном возможных значений. В этой главе мы будем использовать тип integer, занимающий в памяти 4 смежных байта и предназначенный для хранения целых чисел в диапазоне от -2 147 483 648 до +2 147 483 647 8 . Более полные сведения о целых типах вы найдете в гл. 7.
Над целыми числами определены следующие математические операции:


+

+ сложение

-

вычитание

*

умножение

div

деление с отбрасыванием остатка

mod

получение остатка от деления

Спецификой деления является то обстоятельство, что результат может иметь дробный вид: 1/2, 2*3 /5 и т. п. Для хранения дробных чисел в Object Pascal используются вещественные типы (см. п. 7.3.3), вот почему в языке имеются целых две операции деления (div и mod):
var
X,Y: Integer;
begin
X := 5 div 2; // X содержит 2
Y := 5 mod 2 ; // Y содержит 1
end;
Смысл остальных операций совпадает с общепринятым математическим, за тем исключением, что результат не должен выходить из диапазона возможных значений целого типа:
var
X: Integer;
begin
X := 2147483647;
X := X + 1; // Ошибка! Результат +2 147 483 648 выходит
// из допустимого диапазона .
end;
Как и к строкам, к целым числам применимы операции сравнения.
Учебная программа INTMULT
В описываемой ниже программе пользователь вводит два целых числа, а программа вычисляет и показывает их произведение. В этой программе мы также познакомимся с преобразованием типов. На показан вид окна работающей программы.[ В версии Delphi 1 тип Integer занимает 2 байта и содержит число в диапазоне от -32 768 до +32 767. ]
 
Прежде всего обсудим две проблемы, связанные с реализацией программы:

  1. как известить программу о вводе каждого из операндов;
  2. что будет, если пользователь подготовит неверную запись целого числа (например “12.3”).

Суть первой проблемы состоит в том, что подготовленная нами учебная форма fmExampie имеет только одну строку ввода edinput и одну кнопку bbRun (кнопка bbClose используется для прекращения работы программы и эту ее функциональность не следует изменять). Мы могли бы написать программу, которая вводит строку типа
2*3
и после анализа строки выводит результат. Однако логика анализа существенно перегрузит программу и потребует использования в ней средств, с которыми мы пока не знакомы. Значительно проще вставить в форму еще одну кнопку. Тогда щелчок по первой кнопке будет сигналом о том, что в строке ввода подготовлен первый операнд, а щелчок по второй - что готов второй операнд и можно вычислять результат. В этом варианте следует предусмотреть случай, когда щелчок по второй кнопке будет предшествовать щелчку по первой и программа будет вычислять выражение с неопределенным первым операндом. Решение этой дополнительной проблемы состоит в том, чтобы сделать вторую кнопку недоступной или даже невидимой до тех пор, пока не будет введен первый операнд.
Подводя итог, я предлагаю поместить на форму fmExample новую кнопку BitBtn (страница Additional галереи компонентов) так, чтобы она полностью закрыла собой имеющуюся кнопку bbRun, назвать новую кнопку bbResuit (свойство Name), установить для нее сорт (свойство Kind) bkOK и сделать ее временно невидимой (поместить в свойство visible значение False). После такой подготовки в момент начала работы новая кнопка не будет видна и не помешает пользователю щелкнуть по кнопке bbRun. В обработчике события bbRun-click следует спрятать кнопку bbRun и показать кнопку bbResuit, чтобы пользователь смог подтвердить ввод второго операнда. Сделайте необходимые изменения формы для нового проекта, а я пока перейду к обсуждению второй проблемы.
Суть второй проблемы заключается в том, что пользователь может случайно или преднамеренно ввести строку, которая не содержит правильного представления целого числа. Преобразование такой строки к целому числу может привести к аварийному завершению работы программы. Существует множество способов решения этой проблемы, я предлагаю наиболее простой: заменить обычный однострочный редактор edinput на специализированный, способный контролировать ввод пользователя. Удалите из формы редактор edinput (щелкните по нему мышкой и нажмите клавишу Delete) и поместите на его место компонент MaskEdit (страница Additional). Дайте ему прежнее имя edinput (свойство Name) и раскройте диалоговое окно свойства EditMask (Это свойство указывает маску компонента, т. е. определяет, какие символы и в какой последовательности может набирать пользователь в окне ввода.
В строке Input Mask введите
#99999999;1;
В окошке Character for Blanks вместо умалчиваемого символа-заполнителя “_” укажите пробел и закройте окно кнопкой ок. Сформированная нами маска заставит компонент автоматически контролировать ввод пользователя и отвергать любые символы, кроме знаков + или - в первой позиции (элемент маски “#”) и цифр (элементы “9”).
Теперь все готово к кодированию программы.
Дважды щелкните по кнопке bbResuit и введите такой код для обработчика события OnClick этой кнопки:
procedure TfniExample.bbResultClick( Sender: TObject) ;
// Обработка ввода 2-го операнда
begin // Преобразуем текст из edinput в целое число:
Y := StrToInt(Trim(edinput.Text));
// Сообщаем в Memo о вводе 2-го операнда:
mmOutput.Lines.Add('2-й операнд:'+edInput.Text);
// Вычисляем и показываем результат:
mmOutput.Lines.Add('Результат: '+ IntToStr(X)+' * '+IntToStr(Y)+' = '+IntToStr(X*Y));
edinput.Text := ''; // Очищаем ввод
edinput. SetFocus;
// и возвращаем ему фокус
IbOutput.Caption := 'Введите 1-й операнд; bbResuit.Hide;
// Прячем кнопку
bbResuit bbRun.Show;
// и показываем bbRun
end;
Для ввода обработчика события onciick кнопки bbRun нужно сначала с помощью списка выбора в верхней части окна Инспектора объектов отыскать и выбрать компонент bbRun (напомню, он полностью закрыт кнопкой bbResuit), затем дважды щелкнуть в правом столбце строки onciick на странице Events и ввести такой код:
procedure TfmExample.bbRunClick(Sender: TObject);
// Обработка ввода 1-го операнда
begin
// Преобразуем текст из edinput в целое число
Х := StrToInt(Trim(edinput.Text));
// Сообщаем в Memo о вводе 1-го операнда
mmOutput.Lines.Add('1-й операнд: '+edInput.Text);
edinput.Text := ''; // Очищаем ввод
edInput.SetFocus;// и возвращаем ему фокус
IbOutput.Caption := 'Введите 2-й операнд:';
bbResult.Show; // Показываем кнопку bbResult
bbRun.Hide; // и прячем bbRun
end;
Осталось передать фокус ввода компоненту edinput в момент старта программы и определить переменные х и y для хранения операндов. Разыщите в самом начале окна кода программы описание класса TfmExample и отредактируйте его следующим образом:
private
{ Private declarations } X,Y: Integer;.
Затем с помощью списка выбора в окне Инспектора объектов выберите форму fmExampie и после двойного щелчка на строке опАс-tivate страницы Events введите такой обработчик события:
procedure TfmExample.FormActivate(Sender: TObject);
// Подготовка к началу работы
begin
edInput.SetFocus; // Передаем фокус ввода редактору edinput
IbOutput.Caption := 'Введите 1-й операнд:';
end;
Комментарий к программе
С помощью строк
private
{ Private declarations }
X,Y: Integer;
мы определили в классе TfmExample две целочисленные переменные Х и Y, которые после этого стали доступны любым методам этого класса, в том числе обработчикам событий OnClick. Такого рода переменные (их называют полями класса) облегчают взаимодействие методов друг с другом. В нашем случае необходимость в них возникла по той причине, что первый операнд (переменная X) вводится в одном методе (bbRunciick), а используется в другом
(bbResultClick).
Оба обработчика событий onciick содержат почти одинаковые операторы. В начале каждого из них стоит оператор присваивания, в правой части которого содержится выражение
StrToInt(Trim(edinput.Text))
Это выражение состоит из вызова стандартных для Object Pascal функций: сначала вызывается функция Trim , которая возвращает строку-аргумент (в нашем случае edinput.Text) без обрамляющих ее (т. е. ведущих и ведомых) пробелов 9 ; затем с помощью вызова StrToint строка символов преобразуется к целому числу.
Функция преобразования StrToint очень чувствительна к возможным ошибкам символьного представления целого числа. Большая часть возможных ошибок в нашей программе блокируется фильтрующими возможностями редактора MaskEdit и функцией Trim. Программа аварийно завершится, если при щелчке по кнопкам bbRun или bbResuit редактор не содержит текста. Чтобы избежать этого, перед вызовом StrToint вставьте
if edinput.Text ='' ' then Exit;
Этот оператор прекращает дальнейшую работу обработчика в случае, если в окне ввода компонента edinput нет текста.

Методы Show и Hide компонентов-кнопок соответственно показывают или прячут компонент. Спрятанный компонент никак не участвует во взаимодействии с пользователем.

 

 
На главную | Содержание | < Назад....Вперёд >
С вопросами и предложениями можно обращаться по nicivas@bk.ru. 2013 г. Яндекс.Метрика