1 / 72

Polymorphism

Polymorphism. Discrete Mathematics and Its Applications Baojian Hua bjhua@ustc.edu.cn. 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

tamira
Download Presentation

Polymorphism

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  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 Java: int i; i = 99; class S { int x; int y; } S pt = new S (); // compiler complains: i = pt; // Examples from C: int i; i = 99; struct s { int x; int y; }; struct s pt; // 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? typex;

  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. p 88 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?

  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. l … data data data next next next Functions void insertHead (linkedList l, intdata) { linkedList t = (linkedList)malloc (sizeof (*t)); t->data = data; t->next = l->next; l->next = t; return; }

  17. l … data data data next next next 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; }

  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, polydata) { linkedList temp = l->next; while (temp) { if (temp->data == data) // Correct??? return 1; temp = temp->next; } return 0; }

  30. We should turn data into a pointer, and link the pointer here! Client Code #1 #include “linkedList.h” … linkedList list = newLinkedList (); for (int i=0; i<10; i++) { insertHead (list, ???); }

  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? p q

  40. Try #1 int equals (void *p, void *q) { return (p==q); // right? } p q

  41. Try #2 int equals (void *p, void *q) { return (*p==*q); // right? } p q

  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)); } p q

  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)); } p q 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; } p eq x y

  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)); } p q 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); }

More Related