Справочное руководство по Ada 95
3.9.3 Абстрактные типы и подпрограммы
Абстрактный тип — это помеченный тип, предназначенный для использования в качестве родительского типа для расширений типов, но не допускающий создания собственных объектов. Абстрактная подпрограмма — это подпрограмма без тела, которая предназначена для переопределения в какой-то момент при наследовании. Поскольку объекты абстрактного типа создать нельзя, вызов подпрограммы с диспетчеризацией всегда переходит к какому-либо переопределённому телу.
Правила допустимости
Абстрактный тип — это конкретный тип, в объявлении которого используется зарезервированное слово abstract. Объявлять абстрактным можно только помеченный тип.
Подпрограмма, объявленная с помощью abstract_subprogram_declaration (см. 6.1), является абстрактной подпрограммой. Если это примитивная подпрограмма помеченного типа, то помеченный тип должен быть абстрактным.
Для производного типа, если родительский или предковый тип имеет абстрактную примитивную подпрограмму или примитивную функцию с управляемым результатом, то:
- Если производный тип является абстрактным или непомеченным, то унаследованная подпрограмма является абстрактной.
- В противном случае подпрограмма должна быть переопределена неабстрактной подпрограммой; для типа, объявленного в видимой части пакета, переопределение может быть выполнено как в видимой, так и в приватной части. Однако, если тип является формальным типом обобщения, подпрограмма не обязательно должна быть переопределена для самого формального типа; неабстрактная версия обязательно будет предоставлена фактическим типом.
Вызов абстрактной подпрограммы должен быть вызовом с диспетчеризацией; недиспетчеризованные вызовы абстрактной подпрограммы запрещены.
Тип агрегата, или объекта, созданного с помощью object_declaration или allocator, или формального объекта обобщения с режимом in, не должен быть абстрактным. Тип целевого объекта операции присваивания (см. 5.2) не должен быть абстрактным. Тип компонента не должен быть абстрактным. Если тип результата функции является абстрактным, то функция должна быть абстрактной.
Если частичный вид не является абстрактным, соответствующий полный вид не должен быть абстрактным. Если формальный тип обобщения является абстрактным, то для каждой примитивной подпрограммы формального типа, которая не является абстрактной, соответствующая примитивная подпрограмма фактического типа не должна быть абстрактной.
Для абстрактного типа, объявленного в видимой части, абстрактная примитивная подпрограмма не должна объявляться в приватной части, если только она не переопределяет абстрактную подпрограмму, неявно объявленную в видимой части. Для помеченного типа, объявленного в видимой части, примитивная функция с управляемым результатом не должна объявляться в приватной части, если только она не переопределяет функцию, неявно объявленную в видимой части.
Фактическая подпрограмма обобщения не должна быть абстрактной подпрограммой. Префикс attribute_reference для атрибутов Access, Unchecked_Access или Address не должен обозначать абстрактную подпрограмму.
ПРИМЕЧАНИЯ
74 Абстрактность не наследуется; чтобы объявить абстрактный тип, зарезервированное слово abstract должно использоваться в объявлении расширения типа.
75 Тип класса никогда не бывает абстрактным. Даже если класс основан на абстрактном типе, тип класса не является абстрактным, и объект типа класса может быть создан; тег такого объекта будет определять некоторый неабстрактный тип в классе.
Примеры
Пример абстрактного типа, представляющего множество натуральных чисел:
package Sets is
subtype Element_Type is Natural;
type Set is abstract tagged null record;
function Empty return Set is abstract;
function Union(Left, Right : Set) return Set is abstract;
function Intersection(Left, Right : Set) return Set is abstract;
function Unit_Set(Element : Element_Type) return Set is abstract;
procedure Take(Element : out Element_Type;
From : in out Set) is abstract;
end Sets;
subtype Element_Type is Natural;
type Set is abstract tagged null record;
function Empty return Set is abstract;
function Union(Left, Right : Set) return Set is abstract;
function Intersection(Left, Right : Set) return Set is abstract;
function Unit_Set(Element : Element_Type) return Set is abstract;
procedure Take(Element : out Element_Type;
From : in out Set) is abstract;
end Sets;
ПРИМЕЧАНИЯ
76 Примечания к примеру: Учитывая приведенный выше абстрактный тип, можно вывести различные (не абстрактные) расширения типа, представляющие альтернативные реализации множества. Можно использовать битовый вектор, но установить верхнюю границу для наибольшего представимого элемента, в то время как другой может использовать хеш-таблицу, обменивая пространство на гибкость.