Ада-95. Компилятор GNAT

       

Именование тэговых типов


При построении абстракций с применением тэговых типов, необходимо использовать согласованные наименования как для тэговых типов, так и для ассоциируемых с ними пакетов.

Следует заметить, что соглашения по наименованию часто являются источником "религиозных войн".

В следствие этого существует два различных подхода.

Первый подход, за исключением двух специальных случаев, позволяет установить единые соглашения по наименованию описаний, вне зависимости от использования объектно-ориентированных свойств, и при этом он интегрирует в себе использование объектно-ориентированных свойств:

тэговые типы именуются традиционным образом

для имен пакетов экспортирующих какие-либо абстракции, для которых предполагается множество реализаций, используется префикс Abstract_

для имен пакетов предусматривающих функциональные модули, которые могут быть подмешаны ("mixed in") в основную абстракцию используется суффикс _Mixin

Следующий пример, который состоит из двух частей, демонстрирует использование этого варианта соглашений по наименованию.

Для первой части этого примера предположим, что тип Set_Element описывается где-то в другом месте:

package Abstract_Sets is

type Set is abstract tagged private; -- пустое множество function Empty return Set is abstract; -- построение множества из одного элемента function Unit (Element: Set_Element) return Set is abstract; -- объединение двух множеств function Union (Left, Right: Set) return Set is abstract; -- пересечение двух множеств function Intersection (Left, Right: Set) return Set is abstract; -- удаление элемента из множества procedure Take (From : in out Set; Element : out Set_Element) is abstract; Element_Too_Large : exception;

private



type Set is abstract tagged null record; end Abstract_Sets;

with Abstract_Sets; package Bit_Vector_Sets is -- одна реализация абстракции множества type Bit_Set is new Abstract_Sets.Set with private; . . . private

Bit_Set_Size : constant := 64; type Bit_Vector is ... type Bit_Set is new Abstract_Sets.Set with

record

Data : Bit_Vector; end record; end Bit_Vector_Sets;

with Abstract_Sets; package Sparse_Sets is -- альтернативная реализация абстракции множества type Sparse_Set is new Abstract_Sets.Set with private; . . . private

. . . end Sparse_Sets;

<


Вторая часть этого примера демонстрирует использование соглашений по наименованию для смешанных пакетов (mixin packages), которые обеспечивают поддержку оконной системы.

Предположим, что у нас есть тэговый лимитированный приватный тип Basic_Window, описание которого имеет следующий вид:

type Basic_Window is tagged limited private;

Тогда:

generic

type Some_Window is abstract new Basic_Window with private; package Label_Mixin is

type Window_With_Label is abstract new Some_Window with private; . . . private

. . . end Label_Mixin;

generic

type Some_Window is abstract new Basic_Window with private; package Border_Mixin is

type Window_With_Label is abstract new Some_Window with private; . . . private

. . . end Border_Mixin;

Второй подход отображает использование объектно-ориентированных свойств с помощью специальных имен и суффиксов:

пакет абстракции именуется без каких-либо суффиксов, в соответствии с объектом, который этот пакет представляет

смешанные пакеты (mixin packages) именуются в соответствии с аспектами (facet) которые они представляют, используя суффикс _Facet

для главного тэгового типа абстракции используется имя Instance (Object...)

для ссылочного типа (если такой определен), значения которого ссылаются на значения главного тэгового типа, используется имя Reference (Handle, View...)

для последующего описания типа, который является надклассовым типом соответствущим тэговому типу, используется имя Class

Следующий пример демонстрирует использование этого варианта соглашений по наименованию:

package Shape is

subtype Side_Count is range 0 .. 100; type Instance (Sides: Side_Count) is tagged private; subtype Class is Instance'Class; . . . -- операции Shape.Instance private

. . . end Shape;

with Shape; use Shape; package Line is

type Instance is new Shape.Instance with private; subtype Class is Instance'Class; . . . -- переопределенные или новые операции private

. . . end Line;

with Shape; use Shape; generic

type Origin is new Shape.Instance; package With_Color_Facet is

type Instance is new Origin with private; subtype Class is Instance'Class; -- операции для colored shapes private

. . . end With_Color_Facet;

with Line; use Line; with With_Color_Facet; package Colored_Line is new With_Color_Facet (Line.Instance);

<


Простые описания, в этом случае, могут иметь следующий вид:

Red_Line : Colored_Line.Instance; procedure Draw (What : Shape.Instance);

Показанная выше схема соглашений по наименованию корректно работает как в случае использования полных имен, так и при использовании спецификатора use.

При использовании одного и того же имени для всех специфических типов (например type Instance) и надклассовых тпов, одни не полностью квалифицированные имена всегда будут "прятать" другие не полностью квалифицированные имена.

Таким образом, компилятор будет требовать применение полной точечной нотации, чтобы избежать возникновение двусмысленности имен при использовании спецификатора use.

Необходимо использовать такую схему наименований, которая будет согласованной, читабельной и выразительной для представления абстракции.

В идеале, схема наименований для различных способов использования тэговых типов, которые используются для построения различных абстракций, должна быть единой.

Однако если используемая схема соглашений по наименованиям слишком жесткая, то использующие ее фрагменты кода будут выглядеть неестественно с точки зрения читабельности.

При использовании подобных соглашений по наименованию для расширений типа, посредством наследования или подмешивания настраиваемых модулей (generic mixin), достигается читабельность описаний объектов.


Содержание раздела