Шаг 258.
Язык программирования C#. Начала.
Обобщенные типы. Обобщенные классы

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

    Обобщенный класс - это класс, в котором некоторые (или все) типы представлены обобщенными параметрами. Конкретные значения для типов данных определяются на этапе создания объекта класса. Зачем такие классы нужны и какая от них польза? Вообще, обобщенный класс представляет собой конструкцию еще более абстрактную, чем обычный класс. Например, мы хотим создавать объекты с двумя полями. Если мы описываем обычный класс, то в таком классе мы должны указать типы полей. Но если мы описываем обобщенный класс, то типы полей можно указать с помощью обобщенных параметров, а затем, уже при создании объекта, определяются значения типов. Получается, что обобщенный класс представляет собой некий шаблон для обычного класса. То есть он "инкапсулирует" в себе различные классы однотипной структуры - в данном случае это классы, у которых два поля, не важно, какого типа.

    Обобщенные классы удобно использовать в тех случаях, когда объекты, с которыми предстоит иметь дело, должны иметь однотипную структуру, но при этом тип данных может быть разным. Допустим, нам необходимо хранить данные в виде массива и для этой цели предполагается использовать специальные объекты-контейнеры, содержащие соответствующий массив и имеющие методы для работы с данными из массива. Если так, то тип элементов массива отходит на второй план. Его можно реализовать через обобщенный параметр, а в самом обобщенном классе описать универсальные алгоритмы (реализовав их в виде методов), применимые для данных любого типа. А конкретный тип данных, которые будут храниться в контейнере, определяется на этапе создания объекта.


Возвращаясь к примеру с классом с двумя полями, разницу между обычным и обобщенным классом можно определить так. Обычный класс позволяет создавать объекты с двумя полями определенного типа (скажем, int и char). С помощью обобщенного класса можно создавать объекты с двумя полями любого типа.

    Как же описывается обобщенный класс? В принципе, так же, как и обычный (не обобщенный). Только в угловых скобках после названия класса указывается обобщенный параметр (или параметры), обозначающий тип данных. Этот параметр (или параметры) используется в теле класса, отождествляя собой некоторый тип (какой именно, становится понятно при создании объекта на основе класса). А объект класса тоже создается как обычный объект, но кроме названия обобщенного класса в угловых скобках после имени класса указывается значение (или значения) для обобщенных параметров. Шаблон описания обобщенного класса следующий:

class имя класса<параметр(ы) типа> {
  // Код класса
}

    При создании объекта на основе обобщенного класса используем следующий шаблон:

  класс<тип(ы)> объект = new класс<тип(ы)>();

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

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

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace pr258_1
{
    // Обобщенный класс c одним параметром: 
    class Alpha<X> {
        // Поле обобщенного типа: 
        public X code;
        // Конструктор: 
        public Alpha(X a) { 
            code = a;
        }
        // Метод:
        public void show() {
            Console.WriteLine("Поле типа {0}: {1}", typeof(X).Name, code);
        }
    }

    // Обобщенный класс с двумя параметрами: 
    class Bravo<X, Y> {
        // Поля обобщенного типа: 
        public X first; 
        public Y second;
        // Конструктор: 
        public Bravo(X a, Y b) { 
            first = a; 
            second = b;
        }
        // Метод:
        public void show(){
            Console.WriteLine("Первое поле типа {0}: {1}", typeof(X).Name, first); 
            Console.WriteLine("Второе поле типа {0}: {1}", typeof(Y).Name, second);
        }
    }

    // Главный класс: 
    class Program
    {
        static void Main()
        {
            // Создание объектов обобщенного класса:
            Alpha <int> A = new Alpha<int>(123);
            Alpha <string> B = new Alpha<string>("object B");
            Alpha <char> C = new Alpha<char>('C');
            // Вызов методов из объектов обобщенного класса:
            A.show();
            B.show();
            C.show();
            Console.WriteLine();
            // Создание объектов обобщенного класса:
            Bravo <int, char> objA = new Bravo<int, char>(123, 'A');
            Bravo <string, bool> objB = new Bravo<string, bool>("objB", true); 
            Bravo <char, char> objC = new Bravo<char, char>('B', 'C');
            // Вызов методов из объектов обобщенного класса:
            objA.show();
            objB.show();
            objC.show();
            // Задержка:
            Console.ReadLine();
        }
    }
}
Архив проекта можно взять здесь.

    Результат выполнения программы такой:


Рис.1. Результат работы приложения

    Программа простая. В ней мы описываем два обобщенных класса: класс Alpha описан с одним обобщенным параметром (обозначен как X), а класс Bravo описан с двумя обобщенными параметрами (обозначены как X и Y). В описании классов обобщенные параметры указываются в угловых скобках после имени класса.

    В классе Alpha есть поле code обобщенного типа X, а также метод show(), при вызове которого в консольном окне отображается информация о значении обобщенного параметра X и значении поля code. Также в классе Alpha есть конструктор с одним аргументом (типа X). Переданный конструктору аргумент присваивается в качестве значения полю code.

    Класс Bravo подобен классу Alpha, но с поправкой на то, что в классе Bravo два обобщенных параметра (X и Y), два поля (поле first типа X и поле second типа Y), у конструктора два аргумента, а метод show() при вызове отображает значение параметров X и Y, а также значение полей first и second.


Методы в обобщенном классе описываются как обычные: то есть после имени метода обобщенные параметры в угловых скобках указывать не нужно. В случае необходимости они просто используются в методе. Это же относится к вызову методов. Если объект создается на основе обобщенного класса, то значения для обобщенных параметров определяются на этапе создания объекта. При вызове метода из объекта нет необходимости как-то определять эти параметры.

    В главном методе создаются объекты классов Alpha и Bravo, и из этих объектов вызывается метод show(). Хочется верить, что результат выполнения соответствующих команд особых комментариев не требует.


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

    На следующем шаге мы рассмотрим обобщенные структуры.




Предыдущий шаг Содержание Следующий шаг