Ada (798525), страница 11
Текст из файла (страница 11)
Действительно, число полей таких записей и их размеры строгозафиксированы на этапе описания типа записи и никак не могут быть изменены впоследствии.Однако, в реальной жизни, достаточно часто возникают ситуации когда необходимо сделатьструктуру записи зависимой от каких-либо условий.Для решения такого рода задач, Ада разрешает записям содержать дополнительные поля дискриминанты. Такие дополнительные поля являются средством "параметризации" и помогаютвыполнять для записей требуемую настройку.
В этом случае, разные экземпляры записей могутпринадлежать одному и тому же типу, но при этом иметь разный размер и/или разное количествополей.Следует заметить, что значения дискриминантов записей должны быть дискретного илиссылочного типа.5.3.1 Вариантные записиИспользование дискриминантов позволяет конструировать вариантные записи (или, называемыеиначе, записи с вариантами). В этом случае, значение дискриминанта определяет наличие илиотсутствие некоторых полей записи.Рассмотрим следующий пример:type Vehicle is (Bicycle, Car, Truck, Scooter);type Transport (Vehicle_Type : Vehicle) isrecordOwner: String(1..10);Description : String(1..10);-- владелец-- описаниеcase Vehicle_Type iswhen Car =>Petrol_Consumption : Float; -- расход бензинаwhen Truck =>Diesel_Consumption : Float; -- расход соляркиTare: Real; -- вес тарыNet: Real; -- вес неттоwhen others =>null;end case;end record;В представленном описании типа записи Transport, поле Vehicle_Type (vehicle транспортное средство) является дискриминантом.В данном случае, значение дискриминанта должно быть указано при описании экземпляразаписи.
Таким образом, можно создавать различные объекты у которых значениядискриминантов будут отличаться. Заметим также, что при описании таких объектовдопускается указывать только значение дискриминанта, а присваивание значений остальнымполям записи можно выполнять позже.
Агрегаты для записей с дискриминантами должнывключать значение дискриминанта как первое значение. Рассмотрим следующие описания:My_Car: Transport (Car);My_BicycleHis_Car: Transport (Vehicle_Type => Bicycle);: Transport := (Car, "dale", "escort", 30.0);Здесь, переменные My_Car и His_Car, у которых дискриминант имеет значение Car, содержатполя: Owner, Description и Petrol_Consumption. При этом, попытка обращения к такимполям этих переменных как Tare и/или Net будет не допустима. В результате, это приведет кгенерации ошибки ограничения (constraint error), что может быть обнаружено и обработано прииспользовании механизма исключений (exceptions) язака Ада.Следует особо отметить, что несмотря на то, что дискриминант является полем записи,непосредственное присваивание значения дискриминанту запрещено.Также отметим, что в приведенных примерах тип записи, для простоты, имеет только одиндискриминант.
Реально, запись может содержать столько дискриминантов, сколько необходимодля решения конкретной задачи.И в заключение укажем несколько общих особенностей описания записей с вариантами:•••••вариантная часть всегда записывается последнейзапись может иметь только одну вариантную часть, однако внутри вариантной частиразрешается указывать другой раздел вариантовдля каждого значения дискриминанта должен быть указан свой список компонентовальтернатива others допустима только для последнего варианта, она задает всеоставшиеся значения дискриминанта (возможно, и ни одного), которые не былиупомянуты в предыдущих вариантахесли список компонентов варианта задан как null, то такой вариант не содержитникаких компонентов5.3.2 Ограниченные записи (constrained records)Записи My_Car, My_Bicycle и His_Car, которые мы рассматривали выше, называютограниченными.
Для таких записей значение дискриминанта определяется при описанииэкземпляра (переменной) записи. Таким образом, однажды определенный дискриминант впоследствии никогда не может быть изменен. Так, запись My_Bicycle не имеет полей Tare,Net, Petrol_Consumption, и т.д. При этом, компилятор Ады даже не будет распределятьпространство для этих полей.Из всего этого следует общее правило: любой экземпляр записи, который описан с указаниемзначения дискриминанта, будет называться ограниченным (constrained).
Его дискриминантникогда не может принимать значение, отличное от заданного при его описании.5.3.3 Неограниченные записи (unconstrained records)Ада позволяет описывать экземпляры записей без указания начального значения длядискриминанта, тогда запись будет называться неограниченной (unconstrained). В этом случаедискриминант может принимать любое значение на протяжении всего времени существованиязаписи, иначе говоря, дискриминант можно изменять. Очевидно, что в этом случае, компилятордолжен будет распределить достаточное пространство для того, чтобы иметь возможностьразместить наибольшую по размеру запись.Однако, для выполнения вышесказанного, дискриминант записи обязан иметь значение поумолчанию, которое указывается при описании типа записи.type Accounts is (Cheque, Savings);type Account (Account_Type: Accounts := Savings) isrecordAccount_No : Positive;Title: String(1..10);case Account_Type iswhen Savings => Interest : Rate;when Cheque => null;end case;end record;Здесь, дискриминант записи Account имеет значение по-умолчанию Savings.
Теперь, мыможем описать запись:Household_Account : Account;Такая запись будет создана с определенным по-умолчанию значением дискриминанта. Нотеперь, мы позже, при необходимости, можем изменить тип этой записи.Household_Account:= (Cheque, 123_456, "household ");В общем следует заметить, что Ада требует чтобы при описании типа записи значениядискриминантов по-умолчанию либо указывались для всех дискриминантов, либо неуказывались вовсе. При этом, необходимо учесть, что если тип записи описан с указаниемзначений дискриминантов по-умолчанию и, затем, при описании экземпляра записи былоуказано значение дискриминанта, то такой экземпляр записи, в результате, будет ограниченным.Также необходимо особо отметить, что значение дискриминанта неограниченного объектазапрещается изменять независимо от изменения значений других полей, а непосредственноеприсваивание значений дискриминанта, как уже говорилось, вовсе запрещено. Поэтому,единственным способом изменения значения дискриминанта является присваивание значениявсему объекту.
Кроме того, присваивание значений всему объекту сразу является единственнымспособом изменения значений тех компонентов, у которых определение подтипа зависит отзначения дискриминанта. Для пояснения последнего, рассмотрим пример:typetypeProperty is array (Positive range <>) of Float;Man (Number: Positive := 2; Size: Positive := 10) isrecordName: String (1..Size);Prop_Array : Property (1..Number);end record;The_Man : Man;The_Man.Name:= "Ivanov I I";The_Man.Prop_Array := (25.0, 50.0);...The_Man := (NumberSizeName=> 3,=> 8,=> "Pyle I C",Prop_Array => (25.0, 50.0, 160.5));Здесь, первоначально объект The_Man описан как запись, значения дискриминантов которойустанавливаются по умолчанию. Затем, значения дискриминантов изменяются, но это изменениевыполняется согласно требований Ады: осуществляется присваивание значения всейпеременной.5.3.4 Другие использования дискриминантовТакже как и при использовании в качестве селектора выбора варианта в записи, дискриминантможет быть использован для спецификации длины массива, который является компонентомзаписи.type Text (Length: Positive := 20) isrecordValue : String(1..Length);end record;В этом случае длина массива зависит от значения дискриминанта.
Как указано выше, записьможет быть описана как ограниченная (constrained) или как неограниченная (unconstrained).Обычно, такие текстовые записи используются как строки переменной длины для текстовойобработки.Еще одним возможным способом использования дискриминантов могут быть описанияразличных подтипов какого-либо базового типа. В данном случае смысл идеи состоит в том, чтоподтипы можно использовать для создания объектов с конкретными значениямидискриминантов. Такой подход удобен при работе с типами, которые содержат большоеколичество дискриминантов.6. ПодпрограммыВ Аде, также как и во всех современных языках программирования, подпрограммы позволяютпрограммисту группировать инструкции в самостоятельные, логически законченныеалгоритмические единицы, которые, в последствии, могут быть вызваны и выполнены в любомместе программы.
Они являются элементарным базовым средством для повторногоиспользования кода и разделения одной большой задачи на самостоятельные подзадачименьшего размера (декомпозиция). Использование подпрограмм позволяет уменьшить какобщий размер исходных текстов программы, так и общий размер результирующих исполняемыхфайлов. Таким образом, применение подпрограмм облегчает общее управление проектом иупрощает его сопровождение.При этом, подпрограммы Ады обладают некоторыми свойствами, которые будут новыми дляпрограммистов использующих Паскаль и/или Си. Совмещение (overloading), именованныепараметры, значение параметров по-умолчанию, режимы передачи параметров и возвратазначений - все это значительно отличает подпрограммы языка Ада.6.1 Общие сведения о подпрограммахТакже как и в Паскале, подпрограммами Ады являются процедуры и функции.Подпрограммы могут иметь параметры различных типов или не иметь ни одного параметра.При описании механизмов передачи параметров, как правило, используются следующиепонятия:формальныйпараметрПараметр который используется при описании подпрограммы (процедуры или функции).фактическийпараметрОбъект, который передается в подпрограмму при вызове подпрограммы.