330 likes | 462 Views
Object Oriented Programming. OOP(S). One-Slide Summary. There are several (overlapping) kinds of polymorphism: subtype ad-hoc parametric I like generic programming. Metaphysics. Why are we here? What is ‘polymorphism’ anyway? How does this relate to car insurance?. Motivation (1).
E N D
One-Slide Summary • There are several (overlapping) kinds of polymorphism: • subtype • ad-hoc • parametric • I like generic programming
Metaphysics • Why are we here? • What is ‘polymorphism’ anyway? • How does this relate to car insurance?
Motivation (1) • Typical example—containers: class IntList { //... public int get(int i) { //... }} class StringList { // ... public String get(int i) { //... } }
Motivation (2) • Wouldn’t it be nice if we could not-rewrite our code for every element type? • Typical Example Continued: class ObjectList { //... public Object get(int i) { //... }}
Motivation (3) class ObjectList { //... public Object get(int i) { //... }} PLResearcher wes = ...;myList.add(wes) Researcher x = (Researcher)myList.get(0); // Does this work?
Polymorphism PLResearcher wes = ...;myList.add(wes) Researcher x = (Researcher)myList.get(0); • This is polymorphism; our List class now works for different element types • More importantly, we only needed to code it once
Polymorphism (2) • Several types: • Subtype polymorphism (as featured just now) • Ad-hoc polymorphism(similar to overloaded operators) • Parametric polymorphism(same code works for all types)
Guided Questions • Are these kinds of polymorphism mutually exclusive? • Did our List example ‘work for all types?’ • Is the Godfather Object the best way to implement parametric polymorphism?
Problems with Object • Before Object, we could do this: StudentListList teams; // list containing Lists StudentList team_a; StudentList team_b; teams.add(team_a) ; teams.add(team_b);//...// Get the second student from the first teamStudent two_of_one = teams.get(0).get(1)
Problems with Object (2) • Now, we need to cast: List teams; // list containing StudentLists List team_a; List team_b; teams.add(team_a) ; teams.add(team_b);//...// Get the second student from the first teamStudent two_of_one = (Student) ((List)teams.get(0)).get(1)
The Bad Place (3) case teams.get(0) of slist : List => case slist.get(1) of x : Student => x.blah() esac; esac
The Bad Place (4) • Casting is error prone • Might cause runtime errors • No way to ensure homogenous collections • So Java < 5…
Parameterized Types • The Typical Example, continued: class List<T> { //... public T get(int i) { //... }} List<Dog> myList;Dog milo = ...;myList.add(milo) Dog x = myList.get(0);
The Cunning Plan • Let’s add templates to COOL(since we have nothing better to do) • We’ll keep things simple: • one type parameter per class • can’t do ‘new T’ or ‘case e of x : T’(i.e. we really just want to rewrite the casts)
Adding PT to COOL (2) • While we’re here, let’s redefine types altogether: T ::= C | P<t> | t C : Normal Type (e.g. StudentList)P<t> : Parameterized Type (e.g. List<T>)t : A type parameter (e.g. T within List<T>{ … })
Adding PT to COOL (3) • Previously our typing judgments had the form: O, M, C├ e : T • Instead of just C, we need C | P<T> • We’ll call it W
Adding PT to COOL (4) • We now define some new judgments to check types:Let W ├ T : typedenote that T is avalid type within class definition W
Adding PT to COOL (5) • What’s wrong with this picture? • T1” is the result of replacing x with T in T1’ • T2” is the result of replacing x with T in T2’
Adding PT to COOL (6) • Need to add power to ≤ C0≤ C1if C0 inherits C1 { … } C ≤ P<T> if C inherits P<T> { … } P<T> ≤ C if P<t> inherits C { … } P<T> ≤ R<T> if P<t> inherits R<t> { … } t ≤ t ≤ Object • Conclusion: type parameters are only moved around, or used as Object
Guided Questions • Sigh. Did we add any ‘new power’ to COOL? • How might one implement the scheme we just described?
Postmortem • Not all templates are created equal • Java 1.5 Generics are very similar to what we just did with COOL • What if we do allow ‘new’ and such?
Fun with C++ Templates • C++ templates are Soooo 90s • C++ templates are awesome • Awesome = you can build Turing Machines
Fun with C++ Templates (3) • More explainable example: template <int N> struct fact { static const int value = N * fact<N – 1>::value; }; template < > struct fact<1> { static const int value = 1; }; cout << fact<5>::value << endl; // result = ?
Fun with C++ Templates (4) • Note that this looks almost… functional: template <int N> struct fact { static const int value = N * fact<N – 1>::value; }; template < > struct fact<1> { static const int value = 1; }; cout << fact<5>::value << endl; // result = 120 let rec fact n = match n with 1 -> 1 | n -> n * fact(n – 1) (* . . . (but slightly more verbose) *)
Fun with C++ Templates (5) • C++ templates are compile-timead-hoc • Let’s try a less ethereal example: • This works on any EltType that has operator< defined template <typename EltType>EltType & max(EltType & a, EltType & b) { return (a < b ? b : a); }
Fun with C++ Templates (6) • ‘Compare’ this with: • Note that multiple inheritance doesn’t really help here public interface LtComparable { public bool lessThan(LtComparable o); }//... LtComparable max(LtComparable a, LtComparable b) { return (a.lessThan(b) ? b : a); }
Fun with C++ Templates (7) • This is ‘generic programming’ • TA’s Definition: using (compile-time) ad-hoc polymorphism to define ‘Concepts’ • Most common example: the C++ STL
Shorter Version • There are different kinds of polymorphism; not all are created equal • We could add parametric-ish polymorphism to COOL with relative ease • There is a reason why we disallowed dispatch on template parameter instances…
Postpostmortem • We didn’t make it here in 8 minutes • WA4 Due Friday, 11:59pm • re-construct AST from cl-ast file • do some basic checks, e.g. no circular inheritance
Karma Points def build_classes(num): resultlist = [] for i in range(num): cur = dict([(LINE, lines[++lineno] + "\n"), (NAME, lines[++lineno] + "\n"), (INHERITS, build_inherits() + "\n"), (CHILDCOUNT, lines[++lineno] + "\n"), (CHILDREN, build_class_features(int(lines[++lineno]))) ]) resultlist.append(cur) return resultlist NAME,INHERITS,CHILDCOUNT,CHILDREN,LINE = 0, 1, 2, 3, 4 lineno = 0 ast_tree_root = dict f = open(sys.argv[1]) lines = [x.rstrip("\r\n") for x in f.readlines()] f.close()ast_tree_rt = dict( [(NAME, ""), (LINE, ""), (INHERITS, ""), (CHILDCOUNT, lines[0] + "\n"), (CHILDREN, build_classes(int(lines[0]))) ]) sys.stdout.write(ast_tree_rt[CHILDREN][0][NAME])