/* comparing inheritance-based polymorphism and parametric types (generics) */ // for convenience only, everything is made public using System; // An inheritance hierarchy: inheritance is compatible with generics: public interface team { string Name {get;} // property to return name of team } public class footballteam : team { public string name; public string quarterback; public footballteam(string n, string qb) {name=n; quarterback=qb;} public string Name { get { return name; } } } public class hockeyteam : team { public string name; public string goalie; public hockeyteam(string n, string g) {name=n; goalie=g;} public string Name { get { return name; } } } /////////////////////////////////////////////////////////// // 111111**: linked list, version one : using inheritance alone: public interface league { team find(string name); } public class nilteam : league { public team find(string name) { return null; } } public class teamcell : league { public team head; public league next; // rest of the league public teamcell(team h, league n) {head=h; next=n;} public team find(string n) { if (n==head.Name) return head; else return next.find(n); } } // teamcell class //////// test class //////////// public class glist { public static void Main() { league NFL = new teamcell(new footballteam("jets","goodqb"), new teamcell(new footballteam("giants","okqb"), new nilteam())); league NHL = new teamcell(new hockeyteam("islanders","whocares"), new teamcell(new hockeyteam("rangers","whoever"), new nilteam())); // canadian teams: league CA = new teamcell(new footballteam("toronto","qb1"), new teamcell(new hockeyteam("vancouver","goalie1"), new nilteam())); // so far so good, but now we're going to make a mistake intensionally team team1 = NHL.find("rangers"); Console.WriteLine( ((hockeyteam)team1).goalie ); // ok //Console.WriteLine( ((footballteam)team1).quarterback ); // runtime error // This error is not caught at compile time, only at runtime, // because the static type of the object is just "team". /* ******** The following code uses generics ********* */ hockeyteam h1 = new hockeyteam("islanders","whocares"); hockeyteam h2 = new hockeyteam("rangers","whoever"); footballteam f1 = new footballteam("jets","goodqb"); footballteam f2 = new footballteam("giants","greatqb"); LEAGUE H = new TEAMCELL(h1,new TEAMCELL(h2, new NILTEAM())); LEAGUE F = new TEAMCELL(f1,new TEAMCELL(f2, new NILTEAM())); Console.WriteLine(H.find("rangers").goalie); // ok //Console.WriteLine(H.find("rangers").quarterback); // COMPILE TIME ERROR! // The same kind of error is caught at compile time with generics. // However, we can nolonger define a "league" with a mix of // hockeyteams and footballteams. - is this necessarily a bad thing? } // Main } //glist /////////////////////////////////////////////////////////// /* ****** solution using generics ******* */ // 22222** linked list version 2, using parametric types: public interface LEAGUE where A : team { A find(string name); } public class NILTEAM : LEAGUE where A : team { public A find (string name) { return default(A); } } // default(A) is the identity of the A datatype ("", 0, or null); public class TEAMCELL : LEAGUE where A : team { public A head; // the team public LEAGUE next; // rest of the league public TEAMCELL(A h, LEAGUE n) {head=h; next=n;} public A find(string n) { if (n==head.Name) return head; else return next.find(n); } } // TEAMCELL /* There are several issues to understand from this example, including: 1. The price of dynamic types and runtime type-checking 2. natural v.s. artificially polymorphic functions */