Ada (798525), страница 14
Текст из файла (страница 14)
первый формальный параметр ассоциируется спервым фактическим параметром и т.д.procedure Demo(X : Integer; Y : Integer);-- спецификация процедуры...Demo(1, 2);В этом случае, фактический параметр 1 будет подставлен вместо первого формальногопараметра X, а фактический параметр 2 будет подставлен вместо второго формальногопараметра Y.6.3.2 Именованное сопоставлениеДля улучшения читабельности вызовов подпрограмм (а Ада разрабатывалась с учетом хорошейчитабельности) Ада позволяет использовать именованное сопоставление формальных ифактических параметров. В этом случае мы можем ассоциировать имя формального параметра сфактическим параметром. Это свойство делает вызовы подпрограмм более читабельными.procedure Demo(X : Integer; Y : Integer);-- спецификация процедуры...Demo(X => 5, Y => 3 * 45);-- именованное сопоставление-- формальных и фактических-- параметров при вызовеРасположение списка параметров вертикально, также способствует улучшению читабельности.Demo(X => 5,Y => 3 * 45);Поскольку при именованом сопоставлении производится явное ассоциирование междуформальными и фактическими параметрами (вместо неявного ассоциирования, используемого вслучае позиционного сопоставления), то нет необходимости строго придерживаться того жесамого порядка следования параметров, который указан в спецификации подпрограммы.Demo(Y => 3 * 45,X => 5);-- при именованом сопоставлении-- порядок следования параметров-- не имеет значения6.3.3 Смешивание позиционного и именованного сопоставленияАда позволяет смешивать позиционное и именованное сопоставление параметров.
В этомслучае должно соблюдаться следующее условие: позиционно-ассоциированные параметрыдолжны предшествовать параметрам, которые ассоциируются по имени.procedure Square(Result :Number : inout Integer;Integer) isbeginResult := Number * Number;end Square;В результате, показанная выше процедура Square может быть вызвана следующимиспособами:Square(X, 4);Square(X, Number => 4);Square(Result => X, Number => 4);Square(Number => 4, Result => x);Square(Number => 4, X);-- недопустимо, поскольку позиционно-ассоциируемый-- параметр следует за параметром, ассоциируемым-- по имени6.4 Указание значения параметра по-умолчаниюДля любых "in"-параметров ("in" или "in out"), в спецификации подпрограммы можноуказать значение параметра по-умолчанию.
Синтаксис установки значения параметра поумолчанию подобен синтаксису определения инициализированных переменных и имеетследующий вид:with Ada.Text_IO;use Ada.Text_IO;procedure Print_Lines(No_Of_Lines: Integer := 1) isbeginfor Count in 1 .. No_Of_Lines loopNew_Line;end loop;end Print_Lines;Такое описание устанавливает значение параметра No_Of_Lines для случаев когда процедураPrint_Lines вызывается без указания значения этого параметра (позиционного илиименованного).Таким образом, вызов этой процедуры может иметь вид:Print_Lines;Print_Lines(6);-- это печатает одну строку-- переопределяет значение параметра-- установленное по-умолчаниюПодобно этому, если процедура Write_Lines была описана как:with Ada.Text_IO;use Ada.Text_IO;procedure Write_Lines(Letter: in Char := '*';No_Of_Lines : in Integer := 1) isbeginfor I in 1 ..
No_Of_Lines loopfor I in 1 .. 80 loopPut(Letter);end loop;New_Line;end loop;end Write_Lines;то она может быть вызвана следующими способами:Write_Lines;-- для параметров Letter и No_Of_Lines-- используются значения устанавливаемые-- по-умолчаниюWrite_Lines('-');-- значение по-умолчанию - для No_Of_LinesWrite_Lines(no_of_lines => 5);-- значение по-умолчанию - для LetterWrite_Lines('-', 5)-- оба параметра определены6.5 Совмещение (overloading)Поиск новых имен для подпрограмм, которые выполняют одинаковые действия, но спеременными разных типов, всегда является большой проблемой при разработке программногообеспечения. Хорошим примером для иллюстрации такой проблемы является процедураInsert.В подобных случаях, для облегчения жизни программистам, Ада позволяет разнымподпрограммам иметь одинаковые имена, предоставляя механизм который называетсясовмещением (overloading).6.5.1 Совмещение подпрограмм (subprogram overloading)Предоставляя механизм совмещения имен подпрограмм, Ада выдвигает единственноетребование: подпрограммы должны быть распознаваемы (или различимы).
Две подпрограммы,имеющие одинаковые имена, будут распознаваемы если они имеют разный "профиль". Профильподпрограммы характеризуется количеством параметров и их типами, а также, еслиподпрограмма является функцией, - типом возвращаемого значения.Таким образом, пока компилятор может однозначно определить к какой подпрограммеосуществляется вызов, анализируя совпадение профиля вызываемой подпрограммы соспецификациями представленных подпрограмм, - все будет в порядке.
В противном случае, выполучите сообщение об ошибке, указывающее на двусмысленность обращения.procedure Insert(Item : Integer);procedure Insert(Item : Float);-- две процедуры с одинаковыми именами,-- но имеющие разный "профиль"Примерами совмещенных подпрограмм могут служить процедуры Put и Get из стандартногопакета Ada.Text_IO.6.5.2 Совмещение знаков операций (operator overloading)В языках подобных Паскалю знак операции "+" - совмещен. Действительно, он можетиспользоваться для сложения целых и вещественных чисел, и даже строк.
Таким образом,очевидно что этот знак операции используется для представления кода который выполняетабсолютно разные действия.Ада разрешает программистам выполнять совмещение предопределенных знаков операций с ихсобственным кодом. Следует заметить, в Аде, действие выполняемое знаком операции,реализуется путем вызова функции именем которой является знак операции заключенный вдвойные кавычки. При этом, для обеспечения корректной работы механизма совмещения знаковопераций, функция, которая реализует действие знака операции, должна соответствоватьобычному требованию механизма совмещения подпрограмм Ады: она должна быть различима,то есть, ее профиль должен быть уникальным. В некоторых случаях, проблему двусмысленностизнака операции можно преодолеть непосредственно специфицируя имя пакета (рассматриваетсядалее).Кроме того, к функциям которые реализуют действия знаков операций предъявляетсядополнительное требование: они не могут быть выделены в самостоятельно компилируемыемодули, а должны содержаться в другом модуле, таком как процедура, функция или пакет.Рассмотрим простой пример в котором мы хотим предусмотреть возможность сложения двухвекторов:procedure Add_Demo istype Vector is array (Positive range <>) of Integer;A : Vector(1..5);B : Vector(1..5);C : Vector(1..5);function "+"(Left, Right : Vector) return Vector isResult : Vector(Left'First..Left'Last);Offset : constant Natural := Right'First - 1;beginif Left'Length /= Right'Length thenraise Program_Error;-- исключение,-- рассматриваются позжеend if;for I in Left'Range loopResult(I) := Left(I) + Right(I - Offset);end loop;return Result;end "+";beginA := (1, 2, 3, 4, 5);B := (1, 2, 3, 4, 5);C := A + B;end Add_Demo;В этом примере хорошо продемонстрированы многие ранее рассмотренные средства которыехарактерны для языка программирования Ада.6.5.3 Спецификатор "use type"В случае когда какой-либо пакет содержит описания знаков операций, может быть использовананесколько модифицированная форма спецификатора использования use, которая позволяетиспользовать описанные в этом пакете знаки операций без необходимости указания именипакета в качестве префикса.
При этом, в случае использования других компонентов, описанныхв этом пакете, необходимость указания имени пакета в качестве префикса сохраняется. Этамодифицированная форма спецификатора использования имеет следующий вид:use typeимя_типаЗдесь, имя_типа указывает тип данных для которого знаки операций будут использоваться безуказания имени пакета в качестве префикса.7. ПакетыХотя корни Ады лежат в языке Паскаль, концепция пакетов была заимствована из других языковпрограммирования и подверглась значительному влиянию последних наработок в областиразработки программного обеспечения обсуждавшихся в 1970-х годах. Несомненно, что однойиз главных инноваций в этот период была концепция программного модуля (или пакета).Следует заметить, что концепция пакетов не рассматривает то, как программа будетвыполняться.
Идея данного подхода посвящена проблеме построения программного комплекса,облегчению понимания того как он устроен и, следовательно, упрощению его сопровождения.7.1 Общие сведения о пакетах Ады7.1.1 Идеология концепции пакетовПрежде чем непосредственно рассматривать примеры языковых конструкций необходиморазобраться в чем заключается и что предлагает концепция пакетов.Пакет - это средство, которое позволяет сгруппировать логически связанные вычислительныересурсы и выделить их в единый самостоятельный программный модуль. Под вычислительнымиресурсами в этом случае подразумеваются данные (типы данных, переменные, константы...) иподпрограммы которые манипулируют этими данными. Характерной особенностью данногоподхода является разделение самого пакета на две части: спецификацию пакета и тело пакета.Причем, спецификацию имеет каждый пакет, а тело могут иметь не все пакеты.Спецификация определяет интерфейс к вычислительным ресурсам (сервисам) пакета доступнымдля использования во внешней, по отношению к пакету, среде.
Другими словами - спецификацияпоказывает "что" доступно при использовании этого пакета.Тело является приватной частью пакета и скрывает в себе все детали реализациипредоставляемых для внешней среды ресурсов, то есть, тело хранит информацию о том "как"эти ресурсы устроены.Необходимо заметить, что разбиение пакета на спецификацию и тело не случайно, и имеет оченьважное значение. Это дает возможность по-разному взглянуть на пакет. Действительно, дляиспользования ресурсов пакета достаточно знать только его спецификацию, в ней содержитсявся необходимая информация о том как использовать ресурсы пакета.
Необходимость в телепакета возникает только тогда, когда нужно узнать или изменить реализацию чего-либо внутрисамого пакета.Средства построения такой конструкции как пакет дают программисту мощный и удобныйинструмент абстракции данных, который позволяет объединить и выделить в логическизаконченное единое целое данные и код который манипулирует этими данными.