Generic Class Hierarchies


Generic classes can be part of a class hierarchy in just the same way that non-generic classes can. Thus, a generic class can act as a base class or be a derived class. The key difference between generic and non-generic hierarchies is that in a generic hierarchy, any type arguments needed by a generic base class must be passed up the hierarchy by all derived classes. This is similar to the way that constructor arguments must be passed up a hierarchy.

Using a Generic Base Class

Here is a simple example of a hierarchy that uses a generic base class:

 // A simple generic class hierarchy. using System; // A generic base class. class Gen<T> {   T ob;   public Gen(T o) {     ob = o;   }   // Return ob.   public T getob() {     return ob;   } } // A class derived from Gen. class Gen2<T> : Gen<T> {   public Gen2(T o) : base(o) {     // ...   } } class GenHierDemo {   public static void Main() {     Gen2<string> g2 = new Gen2<string>("Hello");     Console.WriteLine(g2.getob());   } }

In this hierarchy, Gen2 inherits the generic class Gen. Notice how Gen2 is declared by the following line:

 class Gen2<T> : Gen<T> {

The type parameter T is specified by Gen2 and is also passed to Gen. This means that whatever type is passed to Gen2 will also be passed to Gen. For example, this declaration:

 Gen2<string> g2 = new Gen2<string>("Hello");

passes string as the type parameter to Gen. Thus, the ob inside the Gen portion of Gen2 will be of type string.

Notice also that Gen2 does not use the type parameter T except to pass it to the Gen base class. Thus, even if a derived class would otherwise not need to be generic, it still must specify the type parameter(s) required by its generic base class.

Of course, a derived class is free to add its own type parameters, if needed. For example, here is a variation on the preceding hierarchy in which Gen2 adds a type parameter of its own:

 // A derived class can add its own type parameters. using System; // A generic base class. class Gen<T> {   T ob; // declare an object of type T   // Pass the constructor an object of   // type T.   public Gen(T o) {     ob = o;   }   // Return ob.   public T getob() {     return ob;   } } // A derived class of Gen that defines a second // type parameter, called V. class Gen2<T, V> : Gen<T> {   V ob2;   public Gen2(T o, V o2) : base(o) {     ob2 = o2;   }   public V getob2() {     return ob2;   } } // Create an object of type Gen2. class GenHierDemo2 {   public static void Main() {     // Create a Gen2 object for string and int.     Gen2<string, int> x =       new Gen2<string, int>("Value is: ", 99);     Console.Write(x.getob());     Console.WriteLine(x.getob2());   } }

Notice the declaration of this version of Gen2, which is shown here:

 class Gen2<T, V> : Gen<T> {

Here, T is the type passed to Gen, and V is the type that is specific to Gen2. V is used to declare an object called ob2, and as a return type for the method getob2( ). In Main( ), a Gen2 object is created in which type parameter T is string, and type parameter V is int. The program displays the following, expected, result:

 Value is: 99

A Generic Derived Class

It is perfectly acceptable for a non-generic class to be the base class of a generic derived class. For example, consider this program:

 // A non-generic class can be the base class // of a generic derived class. using System; // A non-generic class. class NonGen {   int num;   public NonGen(int i) {     num = i;   }   public int getnum() {     return num;   } } // A generic derived class. class Gen<T> : NonGen {   T ob;   public Gen(T o, int i) : base (i) {     ob = o;   }   // Return ob.   public T getob() {     return ob;   } } // Create a Gen object. class HierDemo3 {   public static void Main() {     // Create a Gen object for string.     Gen<String> w = new Gen<String>("Hello", 47);     Console.Write(w.getob() + " ");     Console.WriteLine(w.getnum());   } }

The output from the program is shown here:

 Hello 47

In the program, notice how Gen inherits NonGen in the following declaration:

 class Gen<T> : NonGen {

Because NonGen is not generic, no type argument is specified. Thus, even though Gen declares the type parameter T, it is not needed by (nor can it be used by) NonGen. Therefore, NonGen is inherited by Gen in the normal way. No special conditions apply.




C# 2.0(c) The Complete Reference
C# 2.0: The Complete Reference (Complete Reference Series)
ISBN: 0072262095
EAN: 2147483647
Year: 2006
Pages: 300

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net