Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
CSBasicCourse2ndedPodbelsky / CSBasicCourse2ndedPodbelsky.rtf
Скачиваний:
27
Добавлен:
22.03.2016
Размер:
11.9 Mб
Скачать

18.2. Декларации обобщённых классов "декларация

обобщённого класса"

Рассмотрим формат декларации обобщённого (параметризованного) класса:

модификаторы_классаopt class имя_класса

список_типизирующих_параметров

база_классаopt

ограничения_типизирующих_параметровopt

тело_класса;opt

В приведённом формате обязательными являются: служебное слово class,

имя _ класса

( а

это ,

как

мы

знаем ,

идентификатор )

,

список_типизирующих_параметров

"типизирующие параметры:список"

и

тело_класса. Основным признаком обобщённого класса служит наличие в его

объявлении списка_типизирующих_параметров. Если в объявлении опустить этот

список и, конечно, ограничения типизирующих параметров

"типизирующи

е

параметры:ограничения" ,

то

оно

превратится

в

определение

обычного

(непараметризованного) класса.

Список типизирующих параметров представляет собой заключённую в

угловые скобки < > последовательность разделённых запятыми идентификаторов.

Обратите внимание, что обобщённый класс может быть наследником базового

класса или может реализовать интерфейс, причём и базовый класс и реализуемый

интерфейс, в свою очередь, могут быть параметризованными. В приведённом

формате декларации обобщённого класса возможность наследования обозначена

конструкцией "база_класса" "база класса" .

В стандарте C# для знакомства с обобщёнными классами предлагается

рассмотреть примерно такое объявление (программа 18_01.cs):

class Stack <ItemType> // стек для любых данных

{

static int stackSize = 100; // предельный размер каждого стека

private ItemType[ ] items = new ItemType[stackSize];

private int index = 0; // номер свободного элемента

public void Push(ItemType data) { // поместить в стек

if (index == stackSize)

throw new ApplicationException("Стек переполнен!");

items[index++] = data;

}

public ItemType Pop() { // взять из стека

if (index == 0)

throw new ApplicationException("Стек пуст!");

return items[--index];

}

}

Объявление вводит обобщённый класс с именем Stack для представления

стека,

то

есть

такой

структуры

данных,

которая

позволяет

запоминать

последовательно передаваемые ей значения и извлекать их в порядке, обратном их

поступлению. Поступающие в такой стек значения запоминаются в одномерном

массиве из 100 элементов с именем (ссылкой) items. Особенность объявления этого

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

м

ItemType. Для работы с элементами стека в обобщённом классе определены два

метода – Push() и Pop(). Первый из них получает через параметр некоторое значение

и должен поместить его в массив, связанный со ссылкой items. Метод Pop()

извлекает из массива последний из поступивших туда элементов и возвращает его

значение в точку вызова. Самое важное здесь – использование типизирующего

параметра ItemType. Он определяет тип элементов массива, тип параметра метода

Push() и тип возвращаемого методом Pop() значения.

Основная идея обобщений состоит в том, что декларация обобщенного класса

служит шаблоном для самых разнообразных уже непараметризованных классов,

которые компилятор автоматически определяет (строит), исходя из декларации

обобщённого класса и имеющихся в программе конкретных "обращений" к этой

декларации. Конструкция, которую мы условно назовём "обращением к декларации

обобщённого класса", имеет вид:

имя_обобщённого_класса <список_типизирующих_аргументов>

Здесь каждый типизирующий аргумент "типизирующий аргумент"

– имя

конкретного типа, которое должно заменить в объявлении обобщённого класса все

вхождения соответствующего типизирующего параметра. Соответствие между

типизирующими параметрами декларации обобщённого класса и типизирующими

аргументами в обращении к нему устанавливается по их взаимному расположению.

Здесь используется традиционная

для обращений к методам, функциям и

процедурам схема замещения параметров (формальных параметров) аргументами

(фактическими параметрами).

Если

в

программе ,

содержащей

декларацию

обобщённого

класса

Stack<ItemType>,

использовать конструкцию Stack<char>, то это вводит

специализированный

(

инстанцированный

,

конкретный

)

тип

"тип:специализированный" , порождаемый из декларации обобщённого класса

Stack<ItemType>. В этом специализированном типе, который существует тольк

о

после компиляции программы, все вхождения типизирующего параметра ItemType

заменены типом char. Элементы массива, связанного со ссылкой items , будут иметь

тип char

"тип:char" , метод

Pop() будет возвращать символьные значения,

параметр метода Push() будет символьного типа.

Для обозначения специализированного типа стандарт C# вводит термин

"сконструированный тип

"тип:сконструированный" " (constructed type). Имена

сконструированных

типов

можно

использовать

как

и

обычные

имена

непараметризованных классов. Например, так:

Stack<char> symbols=new Stack<char>();

symbols.Push('A');

char ch= symbols.Pop();

В данном примере создан экземпляр (объект) класса Stack<char>, определена

и связана с этим объектом ссылка symbols с типом того же класса. Затем в стек

помещён символ 'A' и с помощью метода Pop() этот символ получен (извлечён) из

стека.

Точно так же, как для хранения в стеке символьных данных определён класс

Stack<char>, можно вводить сконструированные типы для стеков с элементами

любых типов. Это могут быть как предопределённые типы языка, так и типы,

введённые программистом. Например:

Stack<double>real = new Stack <double>();

real.Push(3.141592);

double pi=real.Pop();

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

с теми данными, "на которые его настроен..." С учётом предыдущего объявления

переменной symbol следующий оператор не верен:

symbols.Push(2.7171); // ошибка компиляции

В декларации обобщённого класса типизирующих параметров может быть

несколько. Ограниченный на их количество нет. Естественное требование – число

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

параметров в декларации обобщённого класса

.

Каждый типизирующий параметр "типизирующий параметр" определяет имя

в пространстве декларации своего класса. Таким образом, имя типизирующего

параметра не может совпадать: с именем другого типизирующего параметра своего

же класса, с именем обобщённого класса, с именем члена этого класса.

Область существования типизирующего параметра включает базу класса,

ограничения типизирующих параметров и тело класса. В отличие от членов класса

типизирующие параметры не распространяются на производные классы. В области

существования типизирующий параметр можно использовать как имя типа.

Соседние файлы в папке CSBasicCourse2ndedPodbelsky