using System; // extend the following visitor pattern with an additional city class // without changing existing code except Main. interface visitor { T visit(NY n); T visit(LA n); } interface city // visitees { T accept(visitor v); // in java T accept(visitor v) } class NY : city { public T accept(visitor v) { return v.visit(this); } } class LA : city { public T accept(visitor v) { return v.visit(this); } } //// sample visitor class tourist : visitor { public string visit(NY ny) { return "goto statue of liberty"; } public string visit(LA ca) { return "goto hollywood"; } }//tourist /// another visitor class collegestudent : visitor { public int visit(NY ny) {Console.WriteLine("goto NYU"); return 0;} public int visit(LA ca) {Console.WriteLine("gogo UCLA"); return 0;} } public class vex2 { public static void Main() { city[] Cs = {new NY(), new LA()}; visitor v = new tourist(); foreach(city c in Cs) { Console.WriteLine(c.accept(v)); c.accept(new collegestudent()); } test(); // calls function below to test extentions }//Main public static void test() { extvisitor cs2 = new collegestudent2(); city[] Cs = {new NY(), new LA(), new Austin()}; foreach(city c in Cs) c.accept(cs2); Cs[2].accept(new tourist()); // will this compile? visitor v = new foodlover(); foreach(city c in Cs) Console.WriteLine(c.accept(v)); } }// /* Add another city */ class Austin : city { public T accept(visitor v) { //throw new Exception("visitor can't visit Austin"); T ax = default(T); // this is usually null or 0 try { ax = ((extvisitor)v).visit(this); } catch(System.InvalidCastException se) { Console.WriteLine("your visitor can't visit Austin: enter your credit card number to pay for this new feature"); } return ax; //if (v is extvisitor) return ((extvisitor)v).visit(this); //else //throw new Exception("this visitor can't visit Austin"); } public T accept(extvisitor v) { return v.visit(this); } } interface extvisitor : visitor // includes visit(NY), visit(LA) { T visit(Austin tx); } // extend current visitors: class collegestudent2 : collegestudent, extvisitor { public int visit(Austin tx) { Console.WriteLine("go to the University of Texas at Austin"); return 0; } }//collegestudent 2 class food { string name; public food(string n) {name=n;} public override string ToString() { return name; } // overrides object.ToString } // marker interface class pizza : food { public pizza(string n) : base(n) {} } class bbq : food { public bbq(string n) : base(n) {} } class pizzalover : visitor { public pizza visit(NY ny) { return new pizza("thincrust pizza"); } public pizza visit(LA ca) { return new pizza("vegan pizza"); } } // Challenge: can foodlover inherit methods in pizzalover? // unfortunately, this won't compile if we declare that foodlover implements // extvisitor despite the covariance of the type variable for // visitor and extvisitor. The same program works in Java, covariance in // C# is much harder to take advantage of: if we uncomment the : // extvisitor, we would also need to uncomment the two adapter functions // that allows inheritance from the superclass: class foodlover : pizzalover //, extvisitor // won't compile despite out { public food visit(Austin tx) {return new bbq("Franklin's bbq"); } // still need adapter methods to get it to work //public food visit(NY ny) { return base.visit(ny); } //public food visit(LA ca) { return base.visit(ca); } }//foodlover