Download presentation
Presentation is loading. Please wait.
1
Polymorphism Discrete Mathematics and Its Applications Baojian Hua bjhua@ustc.edu.cn
2
Variables and Types Languages such as C, C++ or Java have a relatively strict semantics to variables declaration and use Each variable has a static (declared) type Variables declared before use
3
Examples // Examples from C: int i; i = 99; double f; f = 3.14; // compiler complains i = f; // Examples from Java: class A{} class B{} A a; a = new A (); // compiler complains a = new B();
4
What ’ s Polymorphism? A variable of polymorphic type could hold any type of values poly: various morphism: shapes How to declare and use such kind of variables?
5
What We Want? // Suppose a variable x is polymorphic, we want // to write: x = 99; x = 3.14; x = “hello”; // But how to declare such a variable in // statically typed language as C? // More specific, what the “type” of x should be? type x;
6
Difficulties In C C++ or Java, the compiler automatically allocates space for every declared variable the size of that space is calculated statically at compile-time the detailed data layout is determined
7
Difficulties // Examples: int i; // 4 bytes double f; // 8 bytes struct Point2d { int x; int y; } struct Point2d s; // 8 bytes // So it seems that we can never declare such // kind of a variable in C …
8
The Magic The magic is that: if we want to make a variable x hold any type (size) of data d, then the only way is not to put this data d in the variable x.
9
The Magic // Hummm, thus x must be a pointer (x holds some // data d, but the data d is not in x---an // indirection). // Try #1: int *p; p = malloc (sizeof(int)); *p = 88; // but x could only points to data of size 4 // How to make p point to data of other size? p 88
10
The Magic // Try #2: make p point to float data: int *p; // we want to point to a Point2d p = malloc (8); p->x = 3; p->y = 4; // Try this demo … // What happened here? p 3 4
11
Cheat the Compiler // Try #3: let’s cheat the compiler: int *p; p = malloc (8); ((Point2d *)p)->x = 3; ((Point2d *)p)->y = 4; // Try this demo … p
12
Moral So, every pointer is essentially a polymorphic value could point to value of any type (size) the trick is ugly type conversion (cast) of course, should be consistent Every time we want a polymorphic variable, we declare an arbitrary pointer type But the “ int * ” is a little misleading C ’ s early convention (char *) now C offers “ void * ” compiler emits more meaningful error message
13
Void * // The use of “void *” struct s { int x; int y; }; void *p; p = malloc (sizeof (struct s)); ((struct s *)p)->x = 3; ((struct s *)p)->y = 4; // Try this demo … p
14
Polymorphic Data Structures Structure: relationships linear, tree, graph, hash, … Data structures: relationships between data not the data themselves Polymorphic data structures data are polymorphic Next, I ’ ll take linear list as a running example
15
Linear List (Linked-based) // a list of integers: typedef struct linkedListStruct *linkedList; struct linkedListStruct { int data; linkedList next; }; void insertHead (linkedList l, int data); int exists (linkedList l, int data);
16
Linear List (Linked-based) void insertHead (linkedList l, int data) { linkedList temp = malloc (sizeof (*temp)); temp->data = data; temp->next = l->next; l->next = temp; return; }
17
Linear List (Linked-based) int exists (linkedList l, int data) { linkedList temp = l->next; while (temp) { if (temp->data == data) // note equality! return 1; temp = temp->next; } return 0; }
18
Client Code #include “linkedList.h” … linkedList list = newLinkedList (); for (int i=0; i<10; i++) { insertHead (list, i); }
19
Linear List (Linked-based) // another linked list of doubles: typedef struct linkedListStruct *linkedList; struct linkedListStruct { double data; linkedList next; }; void insertHead (linkedList l, double data); int exists (linkedList l, double data);
20
Linear List (Linked-based) void insertHead (linkedList l, double data) { linkedList temp = malloc (sizeof (*temp)); temp->data = data; temp->next = l->next; l->next = temp; return; } // See? Code duplicated!
21
Linear List (Linked-based) int exists (linkedList l, double data) { linkedList temp = l->next; while (temp) { if (temp->data == data) // note equality! return 1; temp = temp->next; } return 0; } // See? Code duplicated!
22
Client Code #include “linkedList.h” … linkedList list = newLinkedList (); for (int i=0; i<10; i++) { insertHead (list, i+0.0); }
23
Linear List (Linked-based) // a polymorphic linked list: typedef struct linkedListStruct *linkedList; struct linkedListStruct { void *data; linkedList next; }; void insertHead (linkedList l, void *data); int exists (linkedList l, void *data);
24
Linear List (Linked-based) void insertHead (linkedList l, void *data) { linkedList temp = malloc (sizeof (*temp)); temp->data = data; temp->next = l->next; l->next = temp; return; }
25
Linear List (Linked-based) int exists (linkedList l, void *data) { linkedList temp = l->next; while (temp) { if (temp->data == data) // Right??? return 1; temp = temp->next; } return 0; }
26
Client Code #include “linkedList.h” … linkedList list = newLinkedList (); for (int i=0; i<10; i++) { insertHead (list, ???); } We should turn data d into a pointer p, and link p here!
27
Client Code // a list of “integers” #include “linkedList.h” … linkedList list = newLinkedList (); void *p; for (int i=0; i<10; i++) { p = malloc (sizeof (int)); *((int *)p) = i; insertHead (list, p); }
28
Client Code // a list of “doubles” #include “linkedList.h” … linkedList list = newLinkedList (); void *p; for (int i=0; i<10; i++) { p = malloc (sizeof (double)); *((double *)p) = i+0.0; insertHead (list, p); } // The burden is lifted to user of linkedList!
29
Pros. and Cons. of Polymorphism Pros: code reuse: write once, use in arbitrary contexts ADT: data structures won ’ t change client data (won ’ t know) Cons: Inconsistency (safety issues) Complexity Efficiency We ’ d discuss cons. issues next
30
Problem #1: Inconsistency (Safety Issues) #include “linkedList.h” … linkedList list = newLinkedList (); void *p; for (int i=0; i<10; i++){ p = malloc (sizeof (int)); *((int *)p) = i; insertHead (list, p); } double *f = (double *) listGetHeadData (list); // ever worse: typdef void (*funTy) (); funTy fp = (funTy) listGetHeadData (list); fp ();
31
Cure to Problem #1: Inconsistency (Safety Issues) C has no built-in static or dynamic checking against such inconsistency Runtime error segment fault, core dumped, or even worse In C. It ’ s programmers ’ duty to guarantee this! Important: always keep invariants of our data structures in mind!
32
Problem #2: Complexity int exists (linkedList l, void *data) { linkedList temp = l->next; while (temp) { if (temp->data == data) // Right??? return 1; temp = temp->next; } return 0; }
33
Problem #2: Complexity // Recall the definition of polymorphic variables: void *p, *q; // We want to write a function “equals ()” int equals (void *p, void *q); // How to implement this? pq
34
Problem #2: Complexity // Try #1: int equals (void *p, void *q) { return (p==q); // right? } pq
35
Problem #2: Complexity // Try #2: int equals (void *p, void *q) { return (*p==*q); // right? } pq
36
Cure to Problem #2: Extra Comparing Function // Try #2: typedef int (*eqTy) (void *, void *); int equals (void *p, void *q, tyEq eq) { return (eq (p, q)); } pq
37
Client Code int compInt (void *p, void *q){ return *((int *)p)==*((int *)q); } //////////////////////////////////////// void *p = malloc (sizeof (int)); *((int *)p) = 9; void *q = malloc (sizeof (int)); *((int *)q) = 9; equals (x, y, compInt);
38
Client Code int compPoint2d (void *p, void *q){ …; return (p->i==q->i && p->f==q->f); } //////////////////////////////////////// void *x = malloc (sizeof (struct Point2d)); *x = …; void *y = malloc (sizeof (struct Point2d)); *y = …; equals (x, y, compPoint2d); // A mimic of so-called “callback”.
39
Cure to Problem #2: Function Pointers in Data int equals (void *p, void *q) { return (p->eq (p, q)); } pq eq Essential features of OO programming!
40
Problem #3: Efficiency // a list of integers #include “linkedList.h” … linkedList list = newLinkedList (); for (int i=0; i<10; i++) { insertHead (list, i); } // a list of “integers” #include “linkedList.h” … linkedList list = newLinkedList (); void *p; for (int i=0; i<10; i++) { p = malloc (4); *((int *)p) = i; insertHead (list, p); }
41
Boxed Data Polymorphism does not come free data must be heap-allocated, to cope with the “ void * ” pointer convention makes memory management expensive It ’ s programmers ’ duty to recycle garbage Such kind of data are called “ boxed ” and “ void * ” is essentially a mask popularize the technology of garbage collection
42
Case Study Java Generics C++ Templates
43
The Hack Applies to Java // In C void *p; p = malloc(sizeof(int)); *((int *)p) = 99; … printf (“%d\n”, *((int *)p)); equals (p, q, eq); // In Java Object p; p = new Integer (99); … System.out.println (((Integer)p).intValue ()); p.equals (q);
44
Linked List in Java class LinkedList { Object data; LinkedList next; void insert (Object data) {…} Object getFirst () {…} }
45
Client Code import util.LinkedList; LinkedList list = new LinkedList (); for (int i=0; i<10; i++) list.insert (new Integer (i)); // Also Ok for a list of strings: for (int i=0; i<10; i++) list.insert (new String (“hello”));
46
Problem #1: Inconsistency (Safety Issues) import util.LinkedList; LinkedList list = new LinkedList (); for (int i=0; i<10; i++) list.insert (new Integer (i)); // compile-time error String s = list.getFirst ();
47
Problem #1: Inconsistency (Safety Issues) import util.LinkedList; LinkedList list = new LinkedList (); for (int i=0; i<10; i++) list.insert (new Integer (i)); // run-time exception String s = (String)list.getFirst ();
48
Cure to Problem #1: Generic class LinkedList { X data; LinkedList next; void insert (X data) {…} X getFirst () {…} }
49
Cure to Problem #1: Use of Generic import util.LinkedList; LinkedList list = new LinkedList (); for (int i=0; i<10; i++) list.insert (new Integer (i)); // compile-time error list.insert (new String (“hello”));
50
Cure to Problem #1: Use of Generic import util.LinkedList; LinkedList list = new LinkedList (); for (int i=0; i<10; i++) list.insert (new Integer (i)); // compile-time error list.insert (new String (“hello”)); // compile-time error String s = list.getFirst ();
51
Problem #2: Complexity // Turn back to “equals ()” function int equals (Object q); // How to implement this? pq
52
Cure to Problem #2: Dynamic Method Dispatch Every class has an “ equals ” method, the call to “ equals ” is automatically dispatched to the correct ones in the current called object. pq eq
53
Problem #3: Efficiency // a list of integers #include “linkedList.h” … linkedList list = newLinkedList (); for (int i=0; i<10; i++) { insertHead (list, i); } // a list of “integers” #include “linkedList.h” … linkedList list = newLinkedList (); void *p; for (int i=0; i<10; i++) { p = malloc (4); *((int *)p) = i; insertHead (list, p); }
54
Problem #3: Efficiency Nearly all data in Java are boxed typically heap-allocated space automatically allocated by the compilers transparent to the programmers Rely on garbage collection to recycle dead objects
55
Case Study Java Generics C++ Templates
56
Linked List Template #ifndef LINKED_LIST_H #define LINKED_LIST_H template class LinkedList { public: X data; LinkedList *next; void insertHead (X data); …; }; #endif
57
… and Functions template void LinkedList ::insertHead (X data) { LinkedList *temp = new LinkedList (); temp->data = data; temp->next = this->next; this->next = temp; return; };
58
… and Client Code #include “LinkedList.h” int main () { LinkedList *p = …; LinkedList *q = …; } // which results in (roughly): class LinkedList_int { public: int data; LinkedList_int *next; }; class LinkedList_Point2d { public: Point2d data; LinkedList_Point2d *next; };
59
Static Monomorphization Program code are duplicated Exponential in theory (code blowing) Seldom observed in practice Separate compilation is lost The template can not be compiled alone and the implementation is exposed
Similar presentations
© 2024 SlidePlayer.com. Inc.
All rights reserved.