Читаем Интернет-журнал "Домашняя лаборатория", 2007 №9 полностью

public void TestSum()

{

    SumList list1 =

        new SumList(new IntCalc());

    list1.add("Петр", 33); list1.add("Павел", 44);

    Console.WriteLine("sum= {0}", list1.Sum());

    SumList list2 =

        new SumList (new DoubleCalc());

    list2.add("Петр", 33.33); list2.add("Павел", 44.44);

    Console.WriteLine("sum= {0}", list2.Sum());

    SumList list3 =

        new SumList (new StringCalc());

    list3.add("Мама", " Мама мыла "); list3.add("Маша",

        "Машу мылом!");

    Console.WriteLine("sum= {0}", list3.Sum ());

}

Обратите внимание на создание списков:

SumList list1 =

    new SumList(new IntCalc());

SumList list2 =

    new SumList(new DoubleCalc());

SumList list3 =

    new SumList(new StringCalc());

Как видите, конструктору объекта передается калькулятор, согласованный с типами данных, которые хранятся в списке. Результаты вычислений, полученных при работе с этими списками, приведены на рис. 22.6.



Рис. 22.6.Списки с суммированием


Родовое порождение класса. Предложение using

До сих пор рассматривалась ситуация родового порождения экземпляров универсального класса. Фактические типы задавались в момент создания экземпляра. Это наглядно показывает преимущества применяемой технологии, поскольку очевидно, что не создается дублирующий код для каждого класса, порожденного универсальным классом. И все-таки остается естественный вопрос: можно ли породить класс из универсального класса путем подстановки фактических параметров, а потом спокойно использовать этот класс обычным образом? Такая вещь возможна. Это можно сделать не совсем обычным путем — не в программном коде, а в предложении using, назначение которого и состоит в выполнении подобных подстановок.

Давайте вернемся к универсальному классу OneLinkstack, введенному в начале этой лекции, и породим на его основе вполне конкретный класс IntStack, заменив формальный параметр T фактическим — int. Для этого достаточно задать следующее предложение using;

using IntStack = Generic.OneLinkStack;

Вот тест, в котором создаются несколько объектов этого класса:

public void TestlntStack ()

{

    IntStack stack1 = new IntStack ();

    IntStack stack2 = new IntStack ();

    IntStack stack3 = new IntStack ();

    stack2.put (11); stackl.put (22);

    int x1 = stack1.item(), x2 = stack1.item();

    if ((x1 == x2) && (xl == 22)) Console.WriteLine("OK!");

    stack1.remove(); x2 = stack1.item();

    if ((x1!= x2) && (x2 == 11)) Console.WriteLine("OK!");

    stack1.remove(); x2 = (stack1.empty())? 77:

        stack1.item();

    if ((x1!= x2) && (x2 == 77)) Console.WriteLine("OK!");

    stack2.put (55); stack2.put (66);

    stack2.remove(); int s = stack2.item();

    if (!stack2.empty()) Console.WriteLine(s);

    stack3.put (33 3); stack3.put((int)Math.Sqrt(Math.PI));

    int res = stack3.item();

    stack3.remove(); res += stack3.item();

    Console.WriteLine("res= {0}", res);

}

Все работает заданным образом, можете поверить.


Универсальность и специальные случаи классов

Универсальность — это механизм, воздействующий на все элементы языка. Поэтому он применим ко всем частным случаям классов C#.


Универсальные структуры

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

public struct Point

{

    Т х, у;//координаты точки, тип которых задан параметром

    // другие свойства и методы структуры

}

Универсальные интерфейсы

Перейти на страницу:

Похожие книги