1 / 59

Polymorphism

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

merry
Télécharger la présentation

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

  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. We should turn data d into a pointer p, and link p here! Client Code #include “linkedList.h” … linkedList list = newLinkedList (); for (int i=0; i<10; i++) { insertHead (list, ???); }

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

  34. Problem #2: Complexity // Try #1: int equals (void *p, void *q) { return (p==q); // right? } p q

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

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

  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)); } p q 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> { X data; LinkedList next; void insert (X data) {…} X getFirst () {…} }

  49. Cure to Problem #1: Use of Generic import util.LinkedList; LinkedList<Integer> list = new LinkedList<Integer> (); 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<Integer> list = new LinkedList<Integer> (); 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 ();

More Related