Конечно, в такой крошечной статье невозможно рассказать о языке все, но мы постараемся описать самое важное. Если вы хотите всерьез заняться программированием, лучше все-таки прочитать учебник по этому языку - там все описано намного подробнее.
Переменная
Это, грубо говоря, кусочек памяти, где хранятся какие-то данные. Данные могут быть самыми разнообразными: число, текст, картинка и так далее.
У переменной есть имя, тип и значение. Имя - это то название, по которому к переменной обращаются. Как и все имена в Delphi, оно может состоять только из латинских букв, цифр и знака подчеркивания, причем начинаться с цифры не может. Разницы между большими и маленькими буквами нет.
Это важно: разрывы строки в Delphi имеют то же значение, что и пробел. Поэтому несколько строк кода можно записать в одну, разбив их пробелами, и наоборот - вместо любого пробела можно вставить конец строки. Так что не удивляйтесь, когда в наших примерах обнаружите «разорванный» на две строки вызов функции или что-нибудь подобное.
Значение - это та информация, которая в переменной хранится. Для численной переменной это может быть, например, 723, для строковой - Крокодилы улетают на север, и так далее.
Тип определяет, какого вида данные живут в переменной. Бывают простые типы, а бывают составные. Простые типы - это: Integer - целое число, например, 32. Single - вещественное число, например, 1.41. Boolean - логический тип. Переменные этого типа могут принимать одно из двух значений: true (истина) или false (ложь). Например, 2<2 равно false, потому как это неправда… String - строка. Строки в Delphi записываются в знаках апострофа, например, так: 'крокозябра'.
Чтобы создать переменную, нужно в разделе описаний (чуть ниже я расскажу, что это такое) написать примерно следующее:
Var q : integer;
Слово var - ключевое и объясняет, что речь пойдет о переменной. q - имя переменной. Integer - ее тип. Точка с запятой показывает, что команда закончена.
Можно перечислить сразу несколько переменных, например, так:
Var a, b : integer;
s : string;
Мы получили целые переменные a и b и строковую s.
Составные типы нужны для того, чтобы включить в одну переменную целый набор данных. Это: Массив. Это набор однородных данных, например, десяток чисел. Записывается такой массив так:
var q : array [1..10] of integer;
Это значит, что в массиве q 10 элементов, с 1 по 10, и каждый из них - целое число. Первый из них можно получить как q[1], второй - q[2], и так далее. Mножество. Сравнительно редкий тип, но нам он пригодится. В нем хранятся данные о том, какие элементы из заданного диапазона (например, от 1 до 100) содержатся в некоем множестве. Например, пусть у нас есть множество qset = [2,4,6,8,10]. Проверка 2 in qset выдаст истину, а 3 in qset - ложь. Структура, она же запись. Эта конструкция нужна, чтобы загнать в одну переменную разнородные данные. Например, у нас есть описание бойца для какой-нибудь стратегической игры; оно может выглядеть в программе примерно так…
var q : record Name : string; Hits : integer; X, y, z : single; end; |
Record - как вы уже догадались, обозначение записи, а Name, Hits и т.п. - самостоятельные переменные внутри этой записи, которые также называют полями. Получить к ним доступ из программы можно так: q.Name, q.Hits и т.п. |
Есть и другие типы, но мы в ближайшем будущем без них обойдемся.
Тип
Что такое тип, вы уже в общих чертах поняли из предыдущей главы. Осталось заметить, что типу можно дать новое имя. Например, нашей записи из примера выше можно дать имя Warrior, и написать такой код: В Delphi принято по мере возможности давать имена всем используемым типам; это здорово облегчает понимание и отладку программы. Почему - об этом поговорим в другой раз. |
type Warrior = record
Name : string; Hits : integer; X,y,z : single; end; var q : Warrior; |
Константа
Константа - это просто имя, которому соответствует какое-то значение. Менять там ничего нельзя. Например, если нам часто нужен корень из 2, то, чтобы не вычислять его каждый раз и не писать длинное число, напишем один раз такую строку:
const sq2 = 1.414213562373;
После этого спокойно пишем везде вместо числа sq2 и знаем, что число автоматически туда подставится.
Самое главное применение констант такое. Допустим, мы решили, что в нашей игре может быть максимум 200 солдатиков. Потом (когда большая часть программы уже написана) мы передумали: пусть будет максимум 300. Если мы воспользовались константой, назвав ее, скажем, MaxSoldiers, то нам достаточно в начале программы изменить ее значение. А если нет - то мы будем долго-долго ползать по своему коду в поисках всех мест, где мы написали эти 200 (кто думает, что можно обойтись глобальным поиском - глубоко неправ. Мало ли, чего еще может быть 200 в нашей программе?).
Оператор
Оператор - это отдельная команда, которую должен выполнить компьютер.
Операторы бывают такими: Присваивание. Некоей переменной присваивается значение. Записывается это, например, так:
q := 31 * b + 72
:= - это собственно знак присваивания. По такой команде компьютер вычислит значение выражения (* - знак умножения) и результат запишет в переменную q. Вызов подпрограммы. Просто пишется имя подпрограммы, а в скобках - ее параметры. О подпрограммах см. следующую главу. Блок операторов. Это серия операторов, которая начинается с кодового слова begin и заканчивающаяся словом end. Все, что между ними (отдельные операторы в блоке разделяются точками с запятой) считается одним оператором. После begin точку с запятой ставить не надо - это ошибка! Условный оператор. Выглядит так: if логическое_выражение then оператор else оператор. Если выражение истинно, то выполняется тот оператор, что после then, иначе - тот, что после else. Второй части может и не быть, оператор может заканчиваться той командой, что после then.
Это важно: хотя большинство команд можно смело заканчивать точкой с запятой, перед else точка с запятой стоять не может.
case a of 1: оператор1; 2: оператор2; 3: оператор3; else операторХ; end; |
Если переменная a равна 1, то выполнится оператор1, если 2 - оператор2, и так далее. Если правильное значение вообще не встретилось - выполнится операторХ. |
Пока верно выражение, будет выполняться оператор. Разумеется, в этом операторе неплохо бы предусмотреть какое-то изменение параметров выражения или другой способ выхода из цикла, не то он будет исполняться вечно. Если же с самого начала условие неверно - цикл не выполнится ни единого раза. |
while выражение do оператор; |
repeat оператор; … оператор; until выражение; |
Этот цикл, наоборот, выполняется, пока не станет верным условие в конце цикла. Поскольку проверка делается в конце цикла, хотя бы один раз он обязательно выполнится. |
Этот цикл выполнится 10 раз - пока переменная i пройдет значения от 1 до 10. В теле цикла можно использовать значение переменной-счетчика. Если стартовое значение больше конечного (for i:=10 to 1 do), цикл не выполнится ни разу. Можно считать и в обратную сторону, скажем, от 10 до 0 - тогда вместо кодового слова to (считать вперед) используется downto (считать назад). |
for i:=1 to 10 do оператор; |
Подпрограммы
Подпрограмма - это кусок программы, который выделен отдельно, получил имя и может под этим именем вызываться из других мест. Подпрограммы бывают двух видов - процедура и функция; отличаются они тем, что функция, помимо исполнения самой программы, выдает на выход некое значение, а следовательно, может использоваться в выражении. Например:
q := cos(t);
Здесь вызывается функция «косинус», а ее значение передается в переменную q.
Подпрограмма обладает заголовком (в котором описаны ее параметры), разделом объявлений (где описаны ее внутренние переменные и собственные подпрограммы) и «телом», или кодом, заключенным между ключевыми словами begin и end.
Параметры нужны затем, чтобы вызывать подпрограмму с разными входными данными. Они описываются примерно так же, как переменные, но есть важное исключение. Если не ставить перед параметром слово var, то можно будет передавать в подпрограмму в качестве этого параметра не только переменную, но и выражение. Пример - на врезке («Образец подпрограммы»).
Образец подпрограммы
Function Integr(x : single) : single;
var i,n : integer;
y, y1 : single;
begin
n := 1000;
repeat
y := IntSum(n, x);
y1 := IntSum(n*2, x);
until Abs(y-y1) end;
Разберем подробно этот пример. Первая строка - это заголовок функции; в нем один параметр (вещественное число, может быть и переменной, и выражением). Тип результата - вещественный.
Дальше идут локальные переменные - две целых и две вещественных. Потом начинается код функции. В нем переменной n присваивается значение 1000, потом идет цикл, который выполняется, пока функция Abs от выражения y-y1 не станет меньше внешней переменной Prec. В этом цикле, при каждом его проходе, дважды вызывается функция IntSum.
Наконец, результату функции (Result) присваивается значение переменной y.
Классы
Ну и, наконец, класс - это тип переменной, который очень похож на структуру, но, кроме полей-переменных, у нее есть поля-подпрограммы (их принято называть методами). Переменные типа «класс» называются объектами.
Например, пусть у нас есть объект, который представляет собой того самого солдатика (см. пример в главе о переменных). Добавим к полям, например, подпрограмму Move(аx, ay, az : single). Она будет перемещать солдатика на новое место (изменяя значение полей x, y, z), а заодно делать и другие сопутствующие действия - перерисовывать фигурку, проверять, не столкнулся ли солдатик со стенкой, и так далее.
Зачем это все нужно?
Главный смысл в том, что классовые типы можно наследовать.
Возьмем того же самого солдатика. У него может быть несколько разновидностей: пехотинец, кавалерист, сапер… Для всех этих персонажей есть общие действия (движение, рисование), а есть разные. Поэтому мы опишем движение и рисование для класса TWarrior (названия классов в Delphi принято начинать с заглавной буквы Т, хотя формально это и необязательно), создадим потомков этого класса - TInfantry (пехотинец), TCavalry и т.д. - и уже у них опишем их особые возможности.
Заметим, что кавалеристу надо будет исполнять команду движения не так, как всем остальным: ему нужно еще и переместить свою лошадь. Поэтому мы перепишем для него эту операцию (см. «Пример класса»).
Пример класса
type TWarrior = class
Name : string;
Hits : integer;
X, y, z : single;
Procedure Move (ax, ay, az : single); virtual;
end;
TCavalry = class(TWarrior)
Procedure Move (ax, ay, az : single); override;
end;
var a : TWarrior;
К объявлению процедуры Move мы дописали ключевое слово virtual; оно обозначает, что эту процедуру можно переопределить. В классе TCavalryрядом с этой процедурой - слово override; оно означает: процедура переопределяется.
Теперь переменной а мы можем присвоить значение и TWarrior, и TCavalry. И, если мы вызовем ее метод a.Move(10,10,10), то программа вызовет правильную версию метода, в зависимости от действительного типа переменной. Это - очень удобный механизм, которым мы будем широко пользоваться.
Конструктор
Чтобы создать переменную типа «объект», нужно сперва вызвать его конструктор. Например, так:
a := TCavalry.Create;
Этот конструктор - тоже специальная подпрограмма, которую нужно отдельно описать. Главное, что он делает - собирает объект воедино и подсоединяет к нему правильные методы. В принципе, в теле конструктора можно ничего и не писать, но обычно в нем определяют начальные значения полей класса.
Комментарии
В код программы для лучшей читаемости принято включать комментарии. Это - произвольный текст, который игнорируется компьютером. Комментарий - это либо часть строки, начинающийся с двойного слэша (//), либо текст, заключенный между фигурных скобок ({}) или скобок со звездочкой ( (* *) ). В наших примерах комментарии выделены цветом.
Cтруктура программы
Собственно программа на Delphi - это коротенький код, задача которого - вызвать на экран форму и обслуживающий ее модуль.
Форма - это окно, на котором можно визуально, при помощи мыши, редактировать интерфейс будущей программы, расставляя по ней разнообразные элементы интерфейса (например, меню, кнопки, картинки, окна редактирования текста и т.п.).
Чтобы настроить параметры этих элементов (например, надпись на кнопке или стартовый текст окна редактора), вам пригодится находящееся обычно слева окно инспектора объектов. После того, как это сделано, интерфейс будет готов к работе, и вам останется только определить нестандартные действия, которые будет делать ваша программа. Это вы сделаете в модуле.
Модуль - это программный текст. Изначально, когда вы только создали приложение, он выглядит примерно так, как показано на врезке Структура программы (жирным шрифтом выделены ключевые слова; среда Delphi и сама умеет их выделять):
Структура программы
unit Uni11;
interface
uses Windows, Messages, SysUtilsЕ
type TForm1 = class(TForm)
// перечисление интерфейсных элементов
end;
var Form1 : TForm1;
implementation
...
end.
Что делают эти части?
Unit - название модуля (в данном случае Unit1).
Interface. Весь текст модуля, начиная с этого слова и до слова Implementation, описывает то, что есть в модуле - переменные, функции, классы и так далее. Здесь не пишется код функций и методов - только заголовки. После Implementation идет расшифровка этих заголовков.
Uses - другие модули, которые используются этим. Те функции, элементы интерфейса и т.п., которые в них описаны, сможет использовать наш модуль.
Type, var - уже знакомые вам описания типов и переменных. Здесь же могут быть и функции или процедуры, начатые с соответствующих ключевых слов, но их код будет только после слова Implementation.