Любой, построенный на основе концепции обобщенного типа данных, шаблон класса вправе выступать в качестве предка для своей цепочки классов-наследников. Объявляя дочерний класс, программист принимает решение о статусе параметра обобщенного типа.
Предусмотрены два варианта наследования:
- наследование с сохранением обобщенного типа данных, другими словами, класс-наследник остается шаблоном;
- наследование с явной конкретизацией типа данных, который следует использовать при работе дочернего класса.
type TGenericParent<T>=class {родительский класс с открытым параметром Т} protected fGP republic
procedure SetGP(Value:T); function GetGP:T;
end;
{1 вариант наследования — объявляется новый класс-шаблон} TGenericChild<T>=class(TGenericParent<T>)
//поля и методы класса TGenericChildl end;
{2 вариант — объявляется обычный класс}
TNotGenericChild<T>=class(TGenericParent<integer>)
//поля и методы класса TNotGenericChild end;
В нашем примере описываются два дочерних класса. Первый из них, класс TGenericChild, допускает, что при обращении к свойствам и методам дочернего и родительского классов могут использоваться любые типы данных, поэтому TGenericChild сохраняет все черты шаблона.
Напротив, класс TNotGenericChild перестал быть шаблоном, он явным образом указывает, что класс-предок в состоянии воспринимать только целочисленные данные.
При описании дочернего класса-шаблона разрешается вводить дополнительные параметры, способные работать с обобщенным типом данных, например:
TGenericChild2<T, C>=class(TGenericParent<T>)
Таким образом, в дочернем классе появился дополнительный параметр обобщенного типа.