// class notes for 10/12/202, csc123/252 // go over exam - tail recursion, dynamic scope, dynamic dispatch. //// what does subclass mean? Does not mean subSET: // {a,b} subset of {a,b,c}, smaller set is a subset of a larger set using System; using System.Collections.Generic; class A { public int x=10; public virtual int f() { return 1; } } class B: A, I // inherits x, f { public int y=3; // subclass looks LARGER than superclass public override int f() { return 2; } public void g() { Console.WriteLine(y); } } class C: A { public new int x=20; } interface I { void g(); } /* A class is NOT a set but a DESCRIPTION of a set of objects. Class A describes the set of all objects that contains and int x and an int f(); Public inheritance (:) establishes an IS A relationship: "a circle is a shape, a square is a shape". all B objects are also A objects. class B describes all objects that contain int x, int f() AND int y(), int g(): it's a tighter description but it describes a SMALLER set. */ public class notes1012 { public static void Main() { // B n = new A(); // what's wrong with this? // all B objects are A objects, but are all A objects B objects? NO // what's wrong is not that it "should look like something else" // and not that "it won't compile", but that it's not LOGICAL! // why int x="abc" is wrong? because a string is not an int. object x = "abc"; //this is OK! x = 3.4; // still ok, doubles are also objects A n = new B(); // a B object is an A object (type cast redundant) Console.WriteLine( n.f() ); // prints 2 //n.g(); // prints 3? no. compiler error, why? // but it's not fair! n is a B object and I should be able to call g! ((B)n).g(); // now ok, but there's a problem: downward cast may be wrong! A m = new C(); // also ok //((B)m).g(); // will this compile? casual thinking won't work // runtime error in C#/Java/Kotlin, but no error msg in C++ // remember TOASTER WITH A BALANCE? // type safety means the type of a value does not change. //C q = (C)(object)new B(); // this compiles too I n2 = (I)new B(); // certainly ok (once B declares implements I n2 = (I)n; // n as above, is this ok? no typevariance.main(); // variance test }//main } // let's get back to the visitor pattern example. // each "visit" method is specific to one type of visitor and one type of city. // but how to we figure out which one to call. // Ideally, you'd like to work on your program one component at a time. // but you also want to get to the right component quickly. ////// DO vex2.cs example. class typevariance { public static void main() { object x = "abc"; // no problem, why? object[] X = new string[10]; // do you still believe this is OK? X[0] = 3.11113; X[1] = new A(); // A class from above string s = (string)X[0] + (string)X[1]; // this all compiled! List li = new List(); li.Add("abc"); li.Add("xyz"); Console.WriteLine(li[0]); // prints abc Console.WriteLine(li.Count); // prints 2 //List li2 = new List(); // won't compile // no way to have same outrageous runtime errors as above. }// second main } class list where T:IComparable { public T car; public list cdr; public int length() { int cx = 0; list pointer = this; while (pointer!=null) {pointer=pointer.cdr; cx++;} return cx; }// this function is POLYMORPHIC public T largest() // return largest value in list { T max = this.car; for(list p=this;p!=null;p=p.cdr) { if (p.car.CompareTo(max)>0) max = p.car; // override > } return max; }// largest ////// both of these functions are polymorphic, but in different ways. }// /* vs class list { public Object car; public list cdr; } // what's the advantage of generics? more static type info: list m = new list(); list n = new list(); // 1. convenience: int x = m.car *2; // compiler has more type info int y = (int)m.car * 2; // 2. (much more important than convenience): safety string z = (string)m.car; // NOT a compiler error! // 3. minor performance improvement: no need to check runtime type tag. Now talk about generics in C++, Java and C# templates.cpp, generics.java and generics.cs */