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 are called statically-typed As opposed to Basic, Lisp, etc. A relatively strict semantics on variables declaration and use Each variable must be declared with a static type Variables declared before use Uses should conform to types
3
Examples // Examples from C: int i; i = 99; struct s { int x; int y; }; struct s pt; // compiler complains: i = pt; // Examples from Java: int i; i = 99; class S { int x; int y; } S pt = new S (); // compiler complains: i = pt;
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 we have a variable x which is // polymorphic, we may write: x = 99; x = 3.14; x = “hello”; // But how to declare such a variable in // statically typed language such as C? // More specific, what x’s “type” 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 s { int x; int y; }; struct s pt; // 8 bytes // So it seems that we can never declare such // a polymorphic 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
Try #1 // Hummm, thus x must be a pointer (x holds some // data d, but the data d is not in x itselft--- // via an indirection). // Try #1: int *p; p = (int *)malloc (sizeof(*p)); *p = 88; // but x it seems that p could only point to // integer data (of size 4). // How to make p point to data of other size? p 88
10
Try #2 // Try #2: make p point to struct data: int *p; // we want to point to a Point2d p = (int *)malloc (sizeof(struct s)); p->x = 3; p->y = 4; // Try this demo … // What happened here? p 3 4
11
Try #2 // Try #3: let’s cheat the compiler: int *p; p = (int *)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 (and size) the trick is the ugly type conversion (cast) of course, should be consistent But the type “ int * ” is a little misleading But recall 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
Linked List #1 (Integer List) typedef struct linkedListStruct *linkedList; struct linkedListStruct { int data; linkedList next; }; void insertHead (linkedList l, int data); int exists (linkedList l, int data);
16
Functions void insertHead (linkedList l, int data) { linkedList t = (linkedList)malloc (sizeof (*t)); t->data = data; t->next = l->next; l->next = t; return; } data next data next data next l …
17
Functions int exists (linkedList l, int data) { linkedList temp = l->next; while (temp) { if (temp->data == data) // equality test! return 1; temp = temp->next; } return 0; } data next data next data next l …
18
Client Code #include “linkedList.h” … linkedList list = newLinkedList (); for (int i=0; i<10; i++) { insertHead (list, i); } exists (list, 5); exists (list, 50);
19
Linked List #2 (Double List) typedef struct linkedListStruct *linkedList; struct linkedListStruct { double data; linkedList next; }; void insertHead (linkedList l, double data); int exists (linkedList l, double data);
20
Functions void insertHead (linkedList l, double data) { linkedList t = (linkedList)malloc (sizeof (*t)); t->data = data; t->next = l->next; l->next = t; return; }
21
Functions int exists (linkedList l, double data) { linkedList temp = l->next; while (temp) { if (temp->data == data) // equality? return 1; temp = temp->next; } return 0; }
22
Client Code #include “linkedList.h” … linkedList list = newLinkedList (); for (int i=0; i<10; i++) { insertHead (list, (double)i); } exists (list, 5.0); exists (list, 50.0);
23
Linked List #3 (Point List) typedef struct linkedListStruct *linkedList; struct linkedListStruct { struct s data; linkedList next; }; void insertHead (linkedList l, struct s data); int exists (linkedList l, struct s data);
24
Functions void insertHead (linkedList l, struct s data) { linkedList t = (linkedList)malloc (sizeof (*t)); t->data = data; t->next = l->next; l->next = t; return; }
25
Functions int exists (linkedList l, struct s data) { linkedList temp = l->next; while (temp) { if (temp->data == data) // equality? 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, cookPoint(i, i*i)); } struct s pt1 = cookPoint (5, 5*5); struct s pt2 = cookPoint (50, 50*50); exists (list, pt1); exists (list, pt2);
27
Linked List #4: polymorphic list typedef void *poly; typedef struct linkedListStruct *linkedList; struct linkedListStruct { poly data; linkedList next; }; void insertHead (linkedList l, poly data); int exists (linkedList l, poly data);
28
Functions void insertHead (linkedList l, poly data) { linkedList t = (linkedList)malloc (sizeof (*t)); t->data = data; t->next = l->next; l->next = t; return; }
29
Functions int exists (linkedList l, poly data) { linkedList temp = l->next; while (temp) { if (temp->data == data) // Correct??? return 1; temp = temp->next; } return 0; }
30
Client Code #1 #include “linkedList.h” … linkedList list = newLinkedList (); for (int i=0; i<10; i++) { insertHead (list, ???); } We should turn data into a pointer, and link the pointer here!
31
Client Code #1 // “integers” list #include “linkedList.h” … linkedList list = newLinkedList (); int *p; for (int i=0; i<10; i++) { p = (int *)malloc (sizeof (*p)); *p = i; insertHead (list, p); }
32
Client Code #1 // “integers” list #include “linkedList.h” … linkedList list = newLinkedList (); int *p; for (int i=0; i<10; i++) { p = (int *)malloc (sizeof (*p)); *p = i; insertHead (list, p); } p = (int *)malloc (sizeof (int)); *p = 5; exists (list, p);
33
Client Code #2 // “doubles” list #include “linkedList.h” … linkedList list = newLinkedList (); double *p; for (int i=0; i<10; i++) { p = (double *)malloc (sizeof (*p)); *p = (double)i; insertHead (list, p); }
34
Client Code #3 // “point” list #include “linkedList.h” … linkedList list = newLinkedList (); struct s *p; for (int i=0; i<10; i++) { p = (struct s *)malloc (sizeof (*p)); *p = cookPoint (i, i*i); insertHead (list, p); } // The burden is shifted to the client code!
35
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
36
Problem #1: Inconsistency (Safety Issues) #include “linkedList.h” … linkedList list = newLinkedList (); int *p; for (int i=0; i<10; i++) { p = (int *)malloc (sizeof (int)); *p = i; insertHead (list, p); } // Can we do this? double *f = (double *)listGetHeadData (list); // ever worse: void (*fp)() = (void (*)())listGetHeadData (list); fp ();
37
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 C programmers ’ duty to prevent these! Important: always keep invariants of our data structures in mind! Ask yourself: what ’ s the type?
38
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; }
39
Equality Testing // Recall the definition of polymorphic variables: void *p, *q; // We want to write a function int equals (void *p, void *q); // to compare Contents! Not address! // How to implement this? pq
40
Try #1 int equals (void *p, void *q) { return (p==q); // right? } pq
41
Try #2 int equals (void *p, void *q) { return (*p==*q); // right? } pq
42
Try #3: Comparing Function Pointer as Argument typedef int (*eqTy) (void *, void *); int equals (void *p, void *q, tyEq eq) { return (eq (p, q)); } pq
43
Client Code int compareInt (void *p, void *q) { return *((int *)p)==*((int *)q); } //////////////////////////////////////// int *p = (int *)malloc (sizeof (*p)); *p = 9; int *q = (int *)malloc (sizeof (*q)); *q = 9; equals (p, q, compareInt);
44
Client Code int comparePoint2d (void *p, void *q) { return (p->x==q->x && p->y==q->y); } //////////////////////////////////////// struct s *x = (struct s *)malloc (sizeof (*x)); *x = …; struct s *y = (struct s *)malloc (sizeof (*y)); *y = …; equals (x, y, comparePoint2d); // A mimic of so-called “callback”.
45
Try #4: Function Pointers in Data int equals (void *p, void *q) { return (p->eq (p, q)); } pq eq
46
Point2d Revisited struct Point2d { int (*eq) (void *, void *); int x; int y; }; eq x y
47
Point2d Revisited struct Point2d *newPoint2d (int x, int y) { struct Point2d *p; p = (struct Point2d *)malloc (sizeof (*p)); p->x = x; p->y = y; p->eq = point2dEquals; return p; } eq x y p
48
Point2d Revisited int point2dEquals (void * pt1, void *pt2) { struct Point2d *p = (struct Point2d *)pt1; struct Point2d *q = (struct Point2d *)pt2; return ((p->x == q->x) && (p->y == q->y)); }
49
Try #4: Function Pointers in Data int equals (void *p, void *q) { return (p->eq (p, q)); } pq eq Commonly known as Object-oriented programming (OOP)
50
Problem #3: Efficiency // integer list #include “linkedList.h” … linkedList list = newLinkedList (); for (int i=0; i<10; i++) { insertHead (list, i); } // “integer” list #include “linkedList.h” … linkedList list = newLinkedList (); int *p; for (int i=0; i<10; i++) { p = (int *)malloc (4); *p = i; insertHead (list, p); }
51
Boxed Data Polymorphism does not come free data mostly 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 difficulty of reallocation popularized the technology of garbage collection
52
Extension to other Languages Two flavors of polymorphism so far: ad-hoc void * They are important in that they motivate ideas for “ advanced ” features in other language Next, we ’ d discuss how C++ and Java reflect this observation and I ’ ll also use linked list as running example After that, you should be able to give some comment
53
Case Study Essentially, in C++ or Java, we could also use some form of “ void * ” C++ even supports that directly But we concentrate on: C++ Template Java Generic
54
Linked List Template #ifndef LINKED_LIST_H #define LINKED_LIST_H template class LinkedList { public: X data; LinkedList *next; void insertHead (X data); int exists (X data); }; // function on next slides… #endif
55
… and Functions // Note: these code is in same.h file as above! template void LinkedList ::insertHead (X data) { LinkedList *temp = new LinkedList (); temp->data = data; temp->next = this->next; this->next = temp; return; }
56
… and Functions // Note: these code is in same.h file as above! template int LinkedList ::exists (X data) { LinkedList *temp = this->next; while (temp) { if (temp->data == data) return 1; temp = temp->next; } return 0; }
57
Client Code #include “linkedList.h” int main () { LinkedList *p = …; LinkedList *q = …; for (int i=0; i<10; i++) p->insertHead (i); p->exists (5); q->exists (3.14); }
58
What ’ s a Template? template class LinkedList { public: X data; LinkedList *next; }; // which results in (roughly): class LinkedList_int { public: int data; LinkedList_int *next; }; class LinkedList_double { public: double data; LinkedList_double *next; };
59
Static Monomorphization Program code are duplicated Exponential in theory (code blowing) Seldom observed in practice Separate compilation is lost The template ’ s interface can not be compiled alone and the implementation is exposed
60
Template Rethink the ad-hoc poly in C Any difference? Rethink the problem of poly in C, does template also incur these problems? Why or why not? Security (inconsistency) Complexity Efficiency
61
Case Study C++ Template Java Generic
62
void * ≈ Object // In C void *p; p = (int *)malloc (sizeof(int)); *p = 99; … printf (“%d\n”, *p); equals (p, q, intEq); // In Java Object p; p = new Integer (99); … System.out.println (((Integer)p).intValue ()); p.equals (q);
63
Linked List in Java class LinkedList { Object data; LinkedList next; void insert (Object data) {…} Object getFirst () {…} }
64
Client Code 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”));
65
Problem #1: Inconsistency (Safety Issues) LinkedList list = new LinkedList (); for (int i=0; i<10; i++) list.insert (new Integer (i)); // compile-time error String s = list.getFirst ();
66
Problem #1: Inconsistency (Safety Issues) LinkedList list = new LinkedList (); for (int i=0; i<10; i++) list.insert (new Integer (i)); // shut up the compiler, but raise run-time // exception: String s = (String)list.getFirst ();
67
Cure to Problem #1: Generic class LinkedList { X data; LinkedList next; void insert (X data) {…} X getFirst () {…} }
68
Use of Generic LinkedList list = new LinkedList (); for (int i=0; i<10; i++) list.insert (new Integer (i)); // compile-time error list.insert (new String (“hello”));
69
Cure to Problem #1: Use of Generic 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 ();
70
Problem #2: Complexity // Turn back to “equals ()” function int equals (Object p, Object q); // How to implement this? pq
71
Cure to Problem #2: Dynamic Method Dispatch Every class has an “ equals ” method, the call to “ equals ” is automatically dispatched to the correct one in the current called object. (virtual functions) pq eq
72
Problem #3: Efficiency Nearly all data in Java are boxed objects typically heap-allocated Rely on garbage collection to recycle dead objects user have little control on this used in embedded system?
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.