Rationale for Ada 2005: Exceptions, generics etc
RUSTOPBACKNEXT
ENG |
5. Generic units
@ There are a number of improvements in the area of generics many of which have already been outlined in earlier papers. @ A first point concerns access types. The introduction of types that exclude null means that a formal access type parameter can take the form
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Rationale for Ada 2005: Exceptions, generics etc
@ENGRUSTOPBACKNEXT5. Настраиваемые модули
@ Есть много усовершенствований в области настраиваемых средсв, большинсво которых уже освещалось в более ранних статьях.
@ Первое касается ссылочных типов. Введение типов, которые исключают пустой указатель, означает, что формальный параметр ссылочного типа может принять форму:
|
@ Тогда фактический тип, соответствующий A должен быть ссылочным типом, который исключает пустой указатель. Подобное правило применяется и в обратном направлении - если формальный параметр исключает пустой указатель тогда, фактический параметр должен также исключать пустой указатель. Если бы они оба не соответствовали в этом отношении тогда мог бы возникнуть целый ряд трудностей.
@ Так же, если формальный параметр получен из ссылочного типа
|
@ тогда фактический тип, соответствующий FA должен исключать пустой указатель, если A исключает пустой указатель и наоборот. Половина этого правила реализуется автоматически, так как тип наследуется из типа который исключает пустой указатель, автоматически исключит пустой указатель. Но обратное не верно как упомянуто в более ранней статье где обсуждались ссылочные типы. Если у A есть объявление
|
@ тогда мы можем объявить
|
@ где NA соответствует формальному параметру FA в вышеупомянутой настройке, а NNA нет.
@ Есть также некоторое изменение к формальным производным типам относительно ограниченности (limitedness). В соответствии с изменениями, описанными в статье посвящённой объектно-ориентированной модели, синтаксис теперь разрешает limited быть заявленным явно таким образом
|
@ Однако, это может рассматриваться просто как документационная помощь т.к. фактические типы T, и TT полученые из LT и TLT и так будут ограничены, если типы LT и TLT ограничены.
@ Объекты анонимных ссылочных типов теперь также разрешены как универсальные формальные параметры, таким образом, мы можем написать
|
@ Если подтип формального объекта исключает пустой указатель (как в AN и в FN) тогда фактический объект должен также исключать пустой указатель, но не наоборот. Это контрастирует с правилом для формальных ссылочных типов, рассмотренных выше, когда и формальный тип и фактический тип должны оба одновременно либо исключать пустой указатель либо нет. Отметим кроме того, что у объектных параметров анонимных ссылочных типов может быть режим in out.
@ Если в спецификации самой подпрограммы есть ссылочные параметры, которые исключают пустой указатель как в
|
@ тогда у фактической подпрограммы должны также быть ссылочные параметры, которые исключают пустой указатель и так далее. То же самое правило относится к именным формальным параметрам подпрограммы. Если мы имеем
|
@ тогда у фактического соответствия P должен быть параметр, который исключает пустой указатель, но фактическое соответствие Q может либо иметь либо не иметь исключение пустого указателя. Правило подобно переименованию - "not null" всегда должно выполняться.
@ Напомним, что соответствие объекта и параметра настраиваемой подпрограммы определено в терминах переименования. Рассмотрим пример иллюстрирующий важность асимметрии.
|
@ Это может быть использовано так
|
@ Формальный тип T в универсальном объявлении, как видим, не является ссылочным типом, и нет никакого механизма для того, чтобы применить нулевое исключение к нему. Однако, нет никаких причин по которым при реализация нельзя было бы использовать нулевое исключение.
@ Есть некоторые другие изменения к существующим именованным формальным параметрам подпрограммы. При обсуждения интерфейсов в одной из предыдущих статей рассматривалось включение в Аду 2005 понятия нулевых процедур. Нулевая процедура не имеет никакого тела, но ведет себя, как будто у нее есть тело, состоящее из оператора null. Теперь разрешено использовать нулевую процедуру как возможную форму значения по умолчанию для параметров подпрограммы. Таким образом, есть теперь три возможных формы значения по умолчанию
|
@ Таким образом, если мы имеем
|
@ тогда при реализации, пропуск параметра R
|
@ эквивалентен автоматическому заданию фактической процедуры следующего вида
|
@ Отметим, что конфигурация фактической процедуры конфигурирована до соответствия формальной процедуре.
@ Конечно, нет такого понятия как нулевая функция и указывать null не разрешается как значение по умолчанию для формальной функции.
@ Новый вид параметра подпрограммы частично был введен при обсуждении функций фабрик объектов в статье посвящённой объектно-ориентированной модели. Это - абстрактная формальная подпрограмма. Был приведён пример предопределённой универсальной функции Generic_Dispatching_Constructor
|
@ Здесь формальная функция Constructor - пример абстрактной формальной подпрограммы. Помните, что интерпретация это то, что фактическая функция должна быть операцией диспетчеризации тегового типа, однозначно определенного конфигурацией формальной функции. Фактическая операция может быть конкретной или абстрактной. Формальные абстрактные подпрограммы могут конечно быть процедурами так же как и функциями. Важно то, что имется точно один управляемый (controlled) тип в конфигурации.
@ У формальных абстрактных подпрограмм могут быть значения по умолчанию заданные аналогичным способом. Мы пишем
|
@ Первое конечно, что у значения по умолчанию должны быть идентификатор P и второе, что значение по умолчанию - некоторая функция Unit. Не возможно дать пустой указатель как значение по умолчанию для абстрактного параметра по различным причинам. Значения по умолчанию будут вероятно редко использоваться для абстрактных параметров.
@ Введение интерфейсов в Аде 2005 означает что возможен новый класс универсальных параметров.
@ Таким образом, мы могли бы иметь
|
@ Фактический тип мог бы тогда быть любым интерфейсом. Это весьма маловероятно.
@ Если бы мы хотели гарантировать чтобы у формального интерфейса были определенные операции тогда, то мы могли бы сначала объявить интерфейс с необходимыми операциями
|
@ и тогда
|
@ и тогда фактический интерфейс должен наследоваться из A а так же иметь операции, которые соответствуют Op1 и N1.
@ Формальный интерфейс мог бы определить несколько предков
|
@ где A и B - самостоятельные интерфейсы. И A и B или только один из них могли бы самостоятельно быть дальнейшими формальными параметрами как в
|
@ Эти средства FAB должны быть и A и B как предки; у него могут конечно быть также и другие предки.
@ Синтаксис для формальных теговых типов также изменен, чтобы принять во внимание возможность интерфейсов.
@ Таким образом, мы могли бы иметь
|
@ когда фактический тип должен наследоваться и от тегового типа T и от интерфейсов A и B. Родительский тип T мог бы быть интерфейсом или нормальным теговым типом. Снова некоторые или даже все T, A, и B могли бы быть более ранними формальными параметрами. Также мы можем явно заявить limited (ограниченный), когда все типы предка должны также быть ограничены.
@ Пример этого вида структуры рссматривался при обсуждении печати геометрических объектов в статье посвящённой объектно-ориентированной модели. Мы имели
|
@ Могло бы случиться так, что у нас есть различные интерфейсы все полученные из Printable, которые удовлетворяют различным целям (возможно для различных устройств вывода, лазерного принтера, перфоратора платы и так далее). Мы тогда хотели бы, чтобы универсальный пакет взял любой из этих интерфейсов таким образом
|
@ Формальный интерфейс также может быть отмечен как ограниченный, в этом случае фактический интерфейс также должен быть ограниченым и наоборот.
@ Как обсуждалось в предыдущей статье, интерфейсы могут также быть synchronized, task, или protected. Таким образом мы могли бы иметь
|
@ и тогда фактический интерфейс должен самостоятельно быть интерфейсом задачи. Корреспонденция должна быть точной. Формальный синхронизированный интерфейс может быть согласован только фактическим синхронизированным интерфейсом и так далее.
@ Помните из обсуждения в предыдущей статье, что интерфейс задачи может быть составлен из синхронизированного интерфейса. Эта гибкость не простирается на соответствие фактических и формальных универсальных параметров.
@ Другая мелочь касается объектных параметров ограниченных типов. В Аде 95 следующее незаконно
|
@ Это незаконно в Аде 95, потому что это нет возможности обеспечить фактический параметр. Это объясняется тем что механизм передачи параметров - это инициализация формального объектного параметра фактическим, и это обработывается как присваивание, а оно запрещено для ограниченных типов.
@ Однако, в Аде 2005 инициализация ограниченного объекта агрегатом разрешена, так как значение создаётся на месте, как обсуждалось в более ранней статье. Таким образом, реализация возможна таким образом
|
@ Напомним, что начальное значение также может быть назначено вызовом функции и, таким образом, фактический параметр также может быть функциональным запросом, возвращающим ограниченный тип.
@ Конечное усовершенствование на универсальный механизм передачи параметров касается параметров пакета.
@ В Аде 95 параметры пакета принимают две формы. Имея настраиваемый пакет Q с формальными параметрами F1, F2, F3 мы можем иметь
|
@ и затем фактический пакет, соответствующий формальному P, может быть любой реализацией Q.
@ Альтернативно
|
@ и тогда фактический пакет, соответствующий R, должен быть реализацией Q с указанными фактическими параметрами P1, P2, P3.
@ Во Введении расматривался простой пример использования этих двух форм где пакет Generic_Complex_Arrays берет реализации Generic_Real_Arrays и Generic_Complex_Types, у которых, в свою очередь, есть основной тип с плавающей точкой как их единственный параметр. Жизненно важно, чтобы оба пакета использовали один и тот же тип с плавающей запятой, и это уверено при письме
|
@ Однако, когда имеется несколько параметров, механизм работает не совсем хорошо, как будет показано далее.
@ Первый пример проблемы, использующий новую контейнерную библиотеку, которая будет обсуждаться в некоторых деталях в более поздней статье. Пусть имеются настраиваемые пакеты:
|
@ и
|
@ Мы могли бы пожелать передать реализации обоих из них в некоторый другой пакет с условием, что они оба иллюстрировались с одним и тем же Element_Type. Иначе параметры могут быть несвязаны.</>
@ Было бы естественно заставить пакет Vectors упаковать первый параметр и дать его в форме (<>). Но мы тогда находим, что в Аде 95 мы должны повторить все параметры кроме Element_Type для пакета Hashed_Maps. Таким образом, мы имеем
|
@ Это - неприятность с тех пор, когда мы иллюстрируем HMV, мы должны обеспечить все параметры, требуемые Hashed_Maps даже при том, что мы, должно быть, уже иллюстрировали ихо в другом месте в программе. Предположим, что реализация была
|
@ и предположим также, что мы имеем инстанцию Vectors
|
@ Теперь, когда при реализации инстанции HMV, мы должны написать
|
@ Это является весьма раздражающим. Мало того, что мы должны повторить все вспомогательные параметры Hashed_Maps, но ситуации относительно Vectors и Hashed_Maps искусственно сделаны асимметричными. (Жизнь была бы немного более простой, если бы мы сделали Hashed_Maps первым параметром пакета, но который только иллюстрирует асимметрию). Конечно мы могли более или менее преодолеть асимметрию, передавая все параметры Vectors также, но тогда у HMV будет даже больше параметров. Это скорее побеждает пункт параметров пакета, которые были введены в Аду 95 чтобы избежать огромных списков параметров, которые были в Аде 83.
@ Ада 2005 преодолевает эту проблему, разрешая только некоторым из фактических параметров быть определенными.
@ Любые опущенные параметры обозначеначаются использованием <> нотации таким образом
|
@ В этом случае фактический пакет, соответствующий S, может быть любым пакетом, который является реализацией Q, где первый фактический параметр - P1, но другие два параметра оставляют неопределенными. Мы можем также сократить это к
|
@ Отметим, что нотация <> может использоваться только с именованными параметрами а также c параметрами вида (<>), они теперь могут сокращены до (others => <>).
@ Другой пример
|
@ Показывает, что фактический пакет, соответствующий S может быть любым пакетом, который является реализацией Q, где второй фактический параметр - P2, но другие два параметра оставляют неопределенными. Это можно сократить до
|
@ Используя это новую нотацию, пакет HMV может теперь просто быть описан так
|
@ и наша реализация HMV становится просто
|
@ Некоторые варианты этого примера очевидно возможны. Например вероятно, что реализация Hashed_Maps должна использовать то же самое определение равенства для типа Element_Type что и Vectors. Мы можем гарантировать это следующим образом
|
@ Если это кажется скорее слишком гипотетическим, более конкретным примером могла бы быть настраиваемая функция, которая преобразовывает вектор в список, если у них есть тот же самый тип элемента и равенство. Отметим сначала, что спецификация контейнерного пакета для списков следующая:
|
@ Спецификация настраиваемой функции Convert могла бы быть
|
@ С другой стороны, если мы только заботимся о соответствии типов элементов, а не о равенстве тогда мы могли бы написать:
|
@ Отметим, что, если бы мы полностью изменили роли формальных пакетов тогда, мы не нуждались бы в новой <> нотации, если бы и равенство и типы элементов должны были соответствовать, но это было бы необходимо в случае когда должен был соответствовать только тип элемента.
@ Другие примеры могли бы возникнуть в области численных данных. Предположим, что у нас есть два независимо написанных настраиваемых пакета Do_This и Do_That, которые оба имеют параметры типа с плавающей запятой и несколько других параметров также. Например
|
@ (Это типичный случай для задач связанных с численной обработкой. Авторы ведут себя осторожно и неспособны принять твердые решения о многих аспектах свих алгоритмов и поэтому перекладывают ответственность на пользователя в форме разбухшего списка вспомогательных параметров). Мы теперь желаем написать пакет Super_Solver, который берет реализации и Do_This и Do_That с требованием, чтобы тип с плавающей точкой, используемый для реализации, был тем же самым в каждом случае, но иначе параметры несвязаны. В Аде 95 мы снова вынуждены были повторить набор параметров таким образом
|
@ И когда мы берёмся реализовывать Super_Solver мы должны обеспечить все вспомогательные параметры требуемые для Do_That даже при том, что мы, должно быть, уже реализовали её в другом месте программы.
@ Предположим, что реализация была
|
@ и предположим также, что мы реализовали Do_This так:
|
@ Теперь при реализации Super_Solver мы должны написать:
|
@ Так же как с HMV у нас есть все эти дублированные параметры и искусственная асимметрия между Тем и Этим.
@ На Аде 2005 пакет Super_Solver может быть написан как:
|
@ и реализация Super_Solver становится просто
|
@ Другие примеры связаны с пакетами сигнатуры. Напомним, что пакет сигнатуры один без спецификации. Он может использоваться чтобы гарантировать что группа объектов связана правильным способом, и реализация может тогда использоваться, чтобы идентифицировать группу в целом. Тривиальный пример мог бы быть следующим:
|
@ Реализация General_Vector только утверждает, что у трех указанных типов есть соответствующее отношение. Таким образом мы могли бы написать
|
@ и тогда
|
@ Пакет General_Vector мог тогда использоваться как параметр других пакетов, таким образом сокращая количество параметров.
@ Другим примером может быть сигнатурный пакет для управления наборами. Рассмотрим:
|
@ У нас мог бы тогда быть некоторый другой настраиваемый пакет, который берет реализацию этой сигнатуры набора.
@ Однако, вероятно, что мы должны были бы определить типы элементов, но возможно не тип набора и конечно не всех операций. Так обычно мы имели бы:
|
@ Пример этой методики приводился при рассмотрении возможности включения системы модульных средств в пределах Ады 2005. Хотя считали не соответствующим включать это, использование пакетов сигнатуры было почти существенным, чтобы сделать механизм пригодным для использования. Заинтересованный читатель должен консультироваться с AI-324.
@ В заключении отметим небольшое изменение в синтаксисе реализации подпрограмм состоящее в этом, что индикатор замены (overriding) может использоваться как указано в Секции 7 статьи посвящённой объектно-ориентированной модели. Таким образом (при соответствующих обстоятельствах) мы можем написать
|
@ Это означает, что реализация должна быть заменяемой операцией для некоторого типа.
2010-10-24 00:26:56
. .