C# 4.0 полное руководство - 2011
Шрифт:
static void Main {
// Создать объект класса Gen с параметром типа string.
Gen<String> w = new Gen<String>("Привет", 47);
Console.Write(w.GetOb + " ");
Console.WriteLine(w.GetNum);
}
}
Эта программа дает следующий результат.
Привет 47
В данной программе обратите внимание на то, как класс Gen наследует
class Gen<T> : NonGen {
Класс NonGen не является обобщенным, и поэтому аргумент типа для него не указывается. Это означает, что параметр Т, указываемый в объявлении обобщенного производного класса Gen, не требуется для указания базового класса NonGen и даже не может в нем использоваться. Следовательно, класс Gen наследует от класса NonGen обычным образом, т.е. без выполнения каких-то особых условий.
Переопределение виртуальных методов в обобщенном классе
В обобщенном классе виртуальный метод может быть переопределен таким же образом, как и любой другой метод. В качестве примера рассмотрим следующую программу, в которой переопределяется виртуальный метод GetOb .
// Пример переопределения виртуального метода в обобщенном классе, using System;
// Обобщенный базовый класс, class 'Gen<T> { protected Т ob;
public Gen(T о) { ob = о;
}
// Возвратить значение переменной ob. Этот метод является виртуальным.
public virtual T GetOb {
Console.Write("Метод GetOb из класса Gen" + " возвращает результат: "); return ob;
}
}
// Класс, производный от класса Gen. В этом классе // переопределяется метод GetOb . class Gen2<T> : Gen<T> {
public Gen2 (T o) : base(o) { }
// Переопределить метод GetOb. public override T GetOb {
Console.Write("Метод GetOb из класса Gen2" + " возвращает результат: ") ; return ob;
}
}
// Продемонстрировать переопределение метода в обобщенном классе, class OverrideDemo { static void Main {
// Создать объект класса Gen с параметром типа int.
Gen<int> iOb = new Gen<int>(88);
// Здесь вызывается вариант метода GetOb из класса Gen.
Console.WriteLine(iOb.GetOb);
//А
// Здесь вызывается вариант метода GetOb из класса Gen2.
Console.WriteLine(iOb.GetOb);
}
}
Ниже приведен результат выполнения этой программы.
Метод GetOb из класса Gen возвращает результат: 88 Метод GetOb из класса Gen2 возвращает результат: 99
Как следует из результата выполнения приведенной выше программы, переопределяемый вариант метода GetOb вызывается для объекта типа Gen2, а его вариант из базового класса вызывается для объекта типа Gen.
Обратите внимание на следующую строку кода.
iOb = new Gen2<int>(99);
Такое присваивание вполне допустимо, поскольку iOb является переменной типа Gen<int>. Следовательно, она может ссылаться на любой объект типа Gen<int> или же объект класса, производного от Gen<int>, включая и Gen2<int>. Разумеется, переменную iOb нельзя использовать, например, для ссылки на объект типа Gen2<int>, поскольку это может привести к несоответствию типов.
Перегрузка методов с несколькими параметрами типа
Методы, параметры которых объявляются с помощью параметров типа, могут быть перегружены. Но правила их перегрузки упрощаются по сравнению с методами без параметров типа. Как правило, метод, в котором параметр типа служит для указания типа данных параметра этого метода, может быть перегружен при условии, что сигнатуры обоих его вариантов отличаются. Это означает, что оба варианта перегружаемого метода должны отличаться по типу или количеству их параметров. Но типовые различия должны определяться не по параметру обобщенного типа, а исходя из аргумента типа, подставляемого вместо параметра типа при конструировании объекта этого типа. Следовательно, метод с параметрами типа может быть перегружен таким образом, что он окажется пригодным не для всех возможных случаев, хотя и будет выглядеть верно.
В качестве примера рассмотрим следующий обобщенный класс.
// Пример неоднозначности, к которой может привести // перегрузка методов с параметрами типа.
//
// Этот код не подлежит компиляции, using System;
// Обобщенный класс, содержащий метод Set, перегрузка // которого может привести к неоднозначности, class Gen<T, V> {
Т obi;
V ob2 ;