Особенности объявления и передачи параметров
Процедуры и функции
При наборе текста исходного кода программисты достаточно часто сталкиваются с необходимостью многократно выполнять одни и те же действия на одном или нескольких этапах обработки данных. При тщательной проверке алгоритмов такого рода легко заметить фрагменты кода, одинаковые по выполняемым действиям и различающиеся только значениями исходных данных. В этом случае повторяющаяся группа операторов оформляется в виде самостоятельной программной единицы – подпрограммы – и записывается только один раз, а в соответствующих местах программы обеспечивается лишь обращение к ней.
В языке Pascal подпрограммы реализуются в виде процедур и функций, которые вводятся в программу с помощью своего описания.
Все процедуры и функции в программе должны иметь уникальные имена. Исключение составляют так называемые перегружаемые методы, специально отмеченные директивой overload.
Процедуры
Процедура представляет собой набор сгруппированных вместе операторов, используемых под одним именем. Процедура состоит из заголовка и тела процедуры. Заголовок начинается ключевым словом procedure, затем следуют имя процедуры и при необходимости заключенный в круглые скобки список параметров. Также при необходимости объявление процедуры может завершаться специальными директивами.
После вызова процедуры последовательно выполняются операторы, заключенные между ключевыми словами begin..end. Ключевому слову begin могут предшествовать блоки объявления типов, констант и переменных (type, const и var). Переменные, объявленные внутри тела процедуры, называются локальными. Такое название связано с тем, что жизненный цикл этой переменной начинается с вызовом процедуры и заканчивается в момент ее завершения. Локальные переменные недоступны извне процедуры.
procedure имя_процедуры (параметр1, …, параметрN); директивы;
локальные_объявления
Begin
<операторы>
end;
Рассмотрим следующий пример. Процедура SquareRectangle() вычисляет площадь прямоугольника, а затем выводит на экран результат.
procedure SquareRectangle(X, Y : integer);
Begin
Square:=X*Y;
WriteLn(Square);
end;
Для того чтобы вызвать эту процедуру из программы, необходимо указать имя процедуры и передать ее параметры (соблюдая их последовательность):
SquareRectangle(100, 200);
Функции
Функции, как и процедуры, предназначены для размещения дополнительных блоков внутри основной программы. Единственное отличие функции от процедуры в том, что она всегда должна возвращать вызвавшей ее программе какое-то значение (результат своих действий). Синтаксис написания функции почти аналогичен синтаксису процедуры. Исключение составляет заголовок функции, который должен начинаться с ключевого слова function и заканчиваться типом возвращаемого значения.
functionимя_процедуры (список_параметров) : тип результата; директивы;
[локальные_объявления]
Begin
<операторы>
end;
Вспомним предыдущий пример с расчетом площади прямоугольника и пред-
ставим его в виде функции.
function SquareRectangle(X,Y : integer):integer;
Begin
Result:=X*Y;
end;
Для вызова функции из основной программы также необходимо указать ее
имя и при необходимости список ее параметров.
var Square:integer;
. . .
Square := SquareRectangle(100, 200);
{переменной Square присвоено значение, возвращаемое функцией SquareRectangle}
Особенности объявления и передачи параметров
В процедурах и функциях Delphi различают четыре основных типа параметров:
• Значения.
• Константы; параметр передается в виде константы и объявляется при помощи
ключевого слова const.
• Переменные; параметр объявляется при помощи ключевого слова var.
• Выходные параметры; объявляются при помощи ключевого слова out.
С использованием в роли параметров обычных значений мы уже знакомы из предыдущего материала. Такой способ применяется наиболее часто. Однако при этом вы должны знать, что следующим шагом, позволяющим компилятору Delphi еще лучше оптимизировать код приложения, будет применение константы вместо обычного параметра-значения. Единственным условием определения параметра в виде константы должна быть 100-процентная уверенность в том, что в теле функции этот аргумент не будет претерпевать каких-либо изменений. Вот пример метода из модуля SysUtils:
function DateToStr(const DateTime: TDateTime): string;
Begin
DateTimeToString(Result, ShortDateFormat, DateTime);
end;
Задача функции – преобразовать в текстовый вид значения даты/времени. Обратите внимание, что в теле функции аргумент DateTime не подвергается никаким модификациям, а это значит, что его целесообразно объявить в виде константы.
Как быть, если результат функции невозможно представить одним-единственным значением? Допустим, возникла необходимость одновременно вычислять не только площадь, но и периметр прямоугольника. Есть несколько вариантов решения этой проблемы. Первый вариант находится на поверхности – мы объявляем две специализированные функции. Первая функция вычисляет площадь, а вторая – периметр. Этот вариант достаточно прост, и мы его не рассматриваем.
Второй вариант более оригинален. Мы объявляем тип TMyRec. Это запись с двумя полями, предназначенными для хранения значений площади и периметра.
uses SysUtils, Classes, …;
Type
TMyRec = record
Square, Perimeter : REAL;
end;
А теперь описываем функцию, результатом которой будет данная запись TmyRec:
function MyFunction(SideA, SideB : Real):TMyRec;
Begin
Result.Square:=SideA*SideB;
Result.Perimeter:=2*(SideA+SideB);
end;
На мой взгляд, это весьма элегантное решение нашей задачки: для получения площади и периметра достаточно однократно вызвать функцию MyFunction.
Однако благодаря высокой гибкости языка программирования Delphi, возможные варианты решения поставленной задачи на этом не исчерпываются. Третий способ заключается во включении переменной в перечень параметров функции. Такой способ передачи параметра будем называть передачейпараметра по ссылке.
function MyFunction(SideA, SideB : Real; var Perimeter : Real) : Real;
Begin
Result:=SideA*SideB;
Perimeter:=2*(SideA+SideB);
end;
Площадь прямоугольника мы по привычке возвращаем во внутренний идентификатор Result, а значение периметра присваиваем формальному параметру Perimeter. А дальше вашему вниманию предлагается несколько строк кода, демонстрирующих способ вызова данной функции.
var Square, Perimeter : Real;
Begin
Square:=MyFunction(5, 10, Perimeter);
WriteLn(Square);
WriteLn(Perimeter);
ReadLn;
end;
Как видно из примера, мы объявили две переменные вещественного типа. В переменную Square (предназначенную для хранения площади) результат вычислений помещается уже привычным для нас способом. А переменная, в которую мы намереваемся поместить периметр прямоугольника, передается как формальный параметр. После выполнения функции результат вычислений выводится на экран.
Передача параметра по ссылке пригодится не только для возврата результатов выполнения метода. Параметр-переменная пригодится и для передачи в процедуру какого-то значения. Однако в Delphi есть способ объявления параметров, специализирующихся только на возврате значений. Для их объявления применяют ключевое слово out. Наиболее часто этот тип аргументов применяется при работе с технологиями COM и COBRA.
function Supports(const Instance: IInterface; const IID: TGUID; out Intf): Boolean;
Begin
Result := (Instance <> nil) and (Instance.QueryInterface(IID, Intf) = 0);
end;
Еще одним достоинством языка Object Pascal является возможность передачи в процедуры и функции в качестве параметра массива или даже открытого массива. Посмотрите на пример объявления функции ArraySum() в программе OpenArrayDemo.
program OpenArrayDemo;
{$APPTYPE CONSOLE}
usesSysUtils;
function ArraySum(Param : Array of Integer):integer;
var I : Integer;
Begin
Result:=0;
for I:=Low(Param) to High(Param)do Result:=Result+Param[i];
end;
varSum : Integer;
Begin
Sum:=ArraySum([1,2,3]);
WriteLn(Sum);
ReadLn;
End.
При острой необходимости Delphi позволяет программисту не типизировать параметр.
procedureAssignFile(var F; FileName: string);
Предложенное объявление процедуры AssignFile позволяет в качестве аргумента передавать файл любого типа. В заголовке метода мы можем сразу задать параметру значение по умолчанию. Для этого после объявления типа параметра ставим знак равенства и значение аргумента:
function MyFunc(X:integer, Y:integer = 10):integer;
Begin
result :=X+Y;
end;
Теперь при вызове объявленной таким образом функции из основной программы программисту предоставляется возможность оставить параметр по умолчанию прежним или передать через него новое значение:
var Z : integer;
. . .
Z := MyFunc(2, 20); //параметру Y передано значение 20
. . .
или
Z := MyFunc(2); //параметр Y принимает значение по умолчанию
Перегрузка методов
Поддержка перегружаемых процедур и функций позволяет сократить количество уникальных имен, что, несомненно, упрощает труд программиста.
Как правило, такие функции применяют при выполнении одинаковых действий над разными типами данных.
function Divide(X, Y: Real): Real; overload;
Begin
Result := X/Y;
end;
function Divide(X, Y: Integer): Integer; overload;
Begin
Result := X div Y;
end;
Заметьте, что в приведенном примере имена функций одинаковы. Однако одноименные функции Divide работают с различными типами параметров.
Для того чтобы Delphi распознала процедуру или функцию как перегружаемую, используют ключевое слово overload. Удобство при работе с перегружаемыми функциями заключается в том, что компилятор самостоятельно выясняет, какой тип данных использует вызов, и подставляет адрес нужной функции:
var A : integer; B : real;
. . .
A:= Divide(10, 2); // тип integer
B:= Divide(10.54, 2.64); // тип real
<== предыдущая лекция | | | следующая лекция ==> |
Дивидендная политика | | | Аниматологической помощи. - Обязанности и права медсестры реанимационного отделения. - Деонтологические и правовые особенности работы реаниматологической службы. |
Дата добавления: 2016-03-15; просмотров: 411;