воскресенье, 13 марта 2011 г.

Обзор языка Delphi

Перевод из справочной системы Delphi

Delphi – это высокоуровневый, компилируемый язык строгой типизации, который поддерживает технологии структурного и объектно-ориентированного программирования. Язык Delphi базируется на Object Pascal, что обуславливает хорошую читаемость кода, быструю компиляцию и возможность модульного программирования. Модули Delphi поддерживают набор компонентов и среду разработки RAD Studio. По большей части, описания и примеры в этом руководстве предполагают, что вы уже знакомы с инструментами разработки Embarcadero.


Большинство разработчиков, использующих инструменты разработки приложений Embarcadero, пишут и компилируют свой программный код в интегрированной среде разработки – IDE (Integrated Development Environment). Инструменты разработки Embarcadero берут на себя всю сложную работу по настройке проектов и файлов с программным кодом, такую как, например, обработка информации о связях между программными модулями. Система также накладывает ограничения на организацию программ, которые, строго говоря, не являются частью спецификацию языка Object Pascal. Например, инструменты разработки Embarcadero поддерживают определенные правила именования файлов, компонентов программ, от которых можно отказаться, разрабатывая программный код вне IDE и компилируя его из командной строки.

Это руководство в основном предполагает, что вы работаете в IDE и разрабатываете приложения, которые используют Библиотеку Визуальных Компонентов (VCL – Visual Component Library). В некоторых случаях, однако, специфические правила Delphi отличаются от правил применяемых при программировании на Object Pascal.

Программная организация

Программы Delphi обычно делятся на части, которые называются модулями. Большинство программ начинается с заголовка program, который определяет имя программы. За заголовком программы обычно следует раздел подключения модулей (Uses clause), затем блок объявлений. В разделе подключения модулей перечисляются модули, связываемые с программой. Эти модули могут использоваться совместно несколькими программами, каждая из которых может иметь свой собственный раздел подключения модулей.

Раздел подключения модулей обеспечивает компилятор информацией о зависимостях между модулями. Поскольку эта информация хранится в самих модулях, большинство программ на Delphi не требуют make-файлов, заголовочных файлов или файлов с директивами "include".

Исходные файлы Delphi

Компилятор ожидает обнаружить исходный код в файлах трех типов:

  • Файлы программных модулей (*.pas)
  • Файлы проектов (*.dpr)
  • Файлы пакетов (*.dpk)

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

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

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


Прочие файлы, используемые при создании приложений.

В дополнение к модулям с программным кодом, продукты Embarcadero используют для построения приложений несколько типов файлов, не содержащих программный код Pascal. Эти файлы автоматически обрабатываются IDE:

  • Файлы VCL форм (*.dfm)
  • Файлы ресурсов (*.res)
  • Файлы опций проекта (*.dof)

Форма VCL содержит описание свойств формы и компонентов, которые ей принадлежат. Каждый файл VCL формы представляет одну форму, которая обычно соответствует окну или диалогу в приложении. IDE позволяет просматривать и редактировать эти файлы как текст и сохранять их либо в текстовом (что очень удобно для контроля версий), либо в бинарном виде. Хотя поведение IDE по умолчанию – сохранение файлов форм в текстовом виде, они конечно же обычно не редактируются вручную. Значительно проще редактировать эти файлы при помощи визуальных инструментов разработки Embarcadero. Каждый проект имеет, по крайней мере, одну форму и каждая форма имеет связанный с ней файл модуля (.pas), который по умолчанию имеет такое же имя, как и файл формы.

В дополнение к файлам форм VCL, каждый проект имеет файл ресурсов (.res), который содержит пиктограмму приложения и прочие ресурсы (например, строки). По умолчанию этот файл имеет тоже имя, что и файл проекта (.dpr).

Файл опций проекта (.dof) хранит настройки компилятора и линковшика, информацию о путях поиска и так далее. Каждый проект имеет связанный с ним файл опций проекта, который имеет такое же имя, что и файл проекта (.dpr). Обычно опции, хранящиеся в этом файле устанавливаются при помощи диалогового окна опций проекта (Project Options dialog).

Различные инструменты в IDE хранят информацию в файлах других типов. Файлы настроек рабочего стола (.dsk) хранят информацию об организации окон и прочие опции конфигурации. Файлы настроек рабочего стола могут быть определены для проекта или действовать для среды разработки в целом. Эти файлы напрямую не влияют на компиляцию.

Файлы, генерируемые компилятором

Когда вы в первый раз компилируете приложение или пакет, компилятор для каждого модуля в вашем проекте создает файл скомпилированного модуля (.dcu под Win32). Все .dcu файлы в вашем проекте затем линкуются для создания одного исполняемого файла или пакета. Когда вы в первый раз компилируете пакет компилятор создает файл для каждого модуля, входящего в состав пакета и, затем, создает файл пакета и файл .dcp. Если вы используете переключатель GD, линковщик создает .map файл и .drc файл, который содержит строковые ресурсы и может быть скомпилирован в файл ресурсов.

Когда вы компилируете проект, отдельные модули не перекомпилируются до тех пор, пока:

  • их исходный код не будет изменен
  • компилятор не сможет обнаружить соответствующие .dcu/.dcp файлы
  • вы явно не укажете компилятору на необходимость их повторной обработки
  • не изменится интерфейс модуля, от которого зависит текущий модуль.

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

Примеры программ

Следующие примеры иллюстрируют основные особенности программирования на Delphi. Примеры показывают простые приложения, которые в обычной ситуации не могут быть скомпилированы в IDE. Вы можете скомпилировать их из командной строки.

Простое консольное приложение

Приведенная ниже программа – это простое консольное приложение, которое вы можете скомпилировать и запустить из командной строки:

program Greeting;

{$APPTYPE CONSOLE}

var
  MyMessage: string;

begin
  MyMessage := 'Hello world!';
  Writeln(MyMessage);
end.

Первая строка объявляет программу, названную Greetings. Директива {$APPTYPE CONSOLE} говорит компилятору, что это консольное приложение, предназначенное для запуска из командной строки. Следующая строка объявляет переменную с именем MyMessage, которая содержит строку. (Delphi имеет настоящие строковые типы данных). Далее программа присваивает значение "Hello world!" переменной MyMessage и отправляет ее содержимое в стандартный вывод, используя процедуру WriteLn. Процедура WriteLn объявлена в модуле System, который компилятор автоматически подключает к каждому приложению.

Вы можете набрать эту программу в файл greeting.pas или greeting.dpr и скомпилировать ее, введя dcc32 greeting для создания исполняемого файла Win32.

Результирующая программа выводит сообщение Hello world!

Несмотря на простоту, этот пример отличается по нескольким важным моментам от программ, которые вы, возможно, пишете при помощи инструментария разработки Embarcadero. Прежде всего, это консольное приложение. Инструментарий разработки Embarcadero чаще всего используется для создания приложений с графическим интерфейсом (GUI – Graphic User Interface). Из чего следует то, что, скорее всего, вам не придется вызывать WriteLn. Кроме того, вся программа-пример находится в одном файле. В типичном приложении GUI заголовок программы будет помещен в отдельный файл проекта, который не будет содержать никакой действительной программной логики, кроме нескольких вызовов подпрограмм, объявленных в файлах модулей.

Более сложный пример

Следующий пример демонстрирует программу, разделенную на два файла: файл проекта и файл модуля. Файл проекта, который вы можете сохранить как greeting.dpr выглядит следующим образом:

program Greeting;

{$APPTYPE CONSOLE}

uses
  Unit1;

begin
  PrintMessage('Hello World!');
end.

Первая строка объявляет программу, названную Greeting, которая снова является консольным приложением. Раздел подключения содержит Uses Unit1;, что говорит компилятору, что программа Greetings зависит от модуля Unit1. Наконец программа вызывает процедуру PrintMessage, передавая ей строку 'Hello World!'.

Процедура PrintMessage определена в Unit1. Далее приведен исходный код Unit1, который должен быть сохранен в файле с именем Unit1.pas:

unit Unit1;

interface

procedure PrintMessage(msg: string);

implementation

procedure PrintMessage(msg: string);
begin
   Writeln(msg);
end;

end.

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

Теперь вы можете скомпилировать Greetings из командной строки, введя

dcc32 greeting

для создания исполняемого файла Win32.

Нет необходимости включать Unit1 в аргументы команды. Когда компилятор обрабатывает greeting.dpr, он автоматически просматривает файлы модулей, от которых зависит программа Greetings. Результирующий исполняемый файл делает то же самое, что и наш первый пример: печатает сообщение Hello world!

Приложение VCL

Следующий пример – это приложение, которое использует компоненты VCL в IDE. Эта программа использует автоматически сгенерированные файлы формы и ресурсов, так что скомпилировать одно это приложение из командной строки не получится. Но она иллюстрирует важные особенности языка Delphi. В дополнение к нескольким модулям, это приложение использует классы и объекты.

Программа включает в себя файл проекта и два новых файла модулей. Сначала приведем файл проекта:

program Greeting;

uses
  Forms, Unit1, Unit2;

{$R *.res} { This directive links the project's 
resource file. }

begin
   { Calls to global Application instance }
   Application.Initialize;
   Application.CreateForm(TForm1, Form1);
   Application.CreateForm(TForm2, Form2);
   Application.Run;
end.

Снова наша программа называется Greeting. Она использует три модуля: Forms, который является частью VCL; Unit1, который связан с главной формой приложения (Form1); и Unit2, который связан с еще одной формой (Form2).

Программа производит несколько вызовов объекта Application, который является экземпляром Forms.TApplication , класса, объявленного в модуле Forms. (Каждый проект имеет автоматически генерируемый объект Application). Два из этих вызовов включают метод CreateForm класса Forms.TApplication. Первый вызов CreateForm создает Form1, экземпляр класса TForm1, определенного в Unit1. Второй вызов CreateForm создает Form2, экземпляр класса TForm2, объявленного в Unit2.

Unit1 выглядит следующим образом:

unit Unit1;

interface

uses SysUtils, Types, Classes, Graphics, Controls, 
Forms, Dialogs;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  end;

var
  Form1: TForm1;

implementation

uses Unit2;

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
  begin
    Form2.ShowModal;
  end;

end.

Unit1 создает класс TForm1 (наследуемый от Forms.TForm) и экземпляр этого класса Form1. TForm1 включает в себя кнопку Button1, экземпляр StdCtrls.TButton и процедуру Button1Click, которая вызывается, когда пользователь нажимает кнопку Button1. Button1Click скрывает Form1 и выводит на экран Form2 (вызов Form2.ShowModal).

Важно: В этом примере Form2.ShowModal полагается на использование экранных форм создаваемых автоматически. Такое использование хорошо для примера, но для разработки реальных приложений этот способ не слишком пригоден.
Form2 объявлена в Unit2:
unit Unit2;

interface

uses SysUtils, Types, Classes, Graphics, Controls, 
Forms, Dialogs;

type
TForm2 = class(TForm)
  Label1: TLabel;
  CancelButton: TButton;
  procedure CancelButtonClick(Sender: TObject);
end;

var
  Form2: TForm2;

implementation

uses Unit1;

{$R *.dfm}

procedure TForm2.CancelButtonClick(Sender: TObject);
  begin
    Form2.Close;
  end;

end.

Unit2 создает класс TForm2 и экземпляр этого класса Form2. TForm2 включает кнопку (CancelButton, экземпляр StdCtrls.TButton) и метку (Label1, экземпляр StdCtrls.TLabel). Вы не сможете видеть этого без исходного кода, но Label1 показывает надпись Hello world! , что обозначено в файле формы Form2 Unit2.dfm.

TForm2 объявляет и определяет метод CancelButtonClick, который будет вызываться, в любой момент, когда пользователь будет нажимать CancelButton. Эта процедура (также как и TForm1.Button1Click в Unit1) называется обработчиком события поскольку она реагирует на событие, которое случается в процессе выполнения приложения. Обработчики назначаются определенным событиям в файлах форм Form1 and Form2.

Когда программа Greetings запускается, Form1 выводится на экран, а Form2 невидима. (По умолчанию только первая созданная в файле проекта форма становится видимой при запуске. Она называется главной формой проекта.) Когда пользователь нажимает кнопку на Form1, Form2 показывает приветствие Hello world!. Когда пользователь нажимает CancelButton или кнопку закрытия на заголовке окна, Form2 закрывается.

Комментариев нет:

Отправить комментарий