1 / 54

Polymorphism

Polymorphism. Discrete Mathematics and Its Applications Baojian Hua bjhua@ustc.edu.cn. Variables and Types. Languages such as C or Java have a relative strict semantics to variables use Each variable has a static (declared) type Variables declared before use. Examples.

hollowaym
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 or Java have a relative strict semantics to variables 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 polymorphic typed variable 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? // What the “type” of x should be? type x;

  6. Difficulties • In C or Java, compiler automatically allocates space for every declared variable • And the size of that space is calculated statically (at compile-time).

  7. Difficulties // Examples: int i; // 4 bytes double f; // 8 bytes struct pt2d { int x; double y; } s; // 12 types // 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, then the only way is not to put this data in that variable x.

  9. x 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 *x; x = malloc (sizeof(int)); *x = 88; // but x could only points to data of size 4 // How to make x point to other sized data?

  10. The Magic // Try #2: make x point to float data: int *x; x = malloc (8); *x = 3.14; // Try this demo … // What happened here? *x = 3.14; x

  11. The Magic // Try #3: let’s cheat the compiler: int *x; x = malloc (8); *((double *)x) = 3.14; // Try this demo … x

  12. The Magic // Try #4: a structure: struct s { int i; double f; }; int *x; x = malloc (sizeof (struct s)); ((struct s *)x)->i = 3; ((struct s *)x)->f = 3.14; // Try this demo … x

  13. Moral • So, every pointer is essentially a polymorphic value • could point to any type (size) of value • the trick is ugly type conversion • 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 it offers “void *” • compiler emits more meaningful error message

  14. Void * // The use of “void *” struct s { int i; double f; }; void *x; x = malloc (sizeof (struct s)); ((struct s *)x)->i = 3; ((struct s *)x)->f = 3.14; // Try this demo … x

  15. 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

  16. Linear List (Linked-based) // a list of integers: typedef struct linkedList *linkedList; struct linkedList { int data; linkedList next; }; void insertHead (linkedList l, int data); int lookup (linkedList l, int data);

  17. Linear List (Linked-based) // implementation of “insertHead” void insertHead (linkedList l, int data) { linkedList temp = malloc (sizeof (*temp)); temp->data = data; temp->next = l->next; l->next = temp; return; }

  18. Linear List (Linked-based) // implementation of “lookup” int lookup (linkedList l, int data) { linkedList temp = l->next; while (temp) { if (temp->data == data) // note equality! return 1; temp = temp->next; } return 0; }

  19. Client Code #include “linkedList.h” … linkedList list = newLinkedList (); for (int i=0; i<10; i++) { insertHead (list, i); }

  20. Linear List (Linked-based) // another linked list of doubles: typedef struct linkedList *linkedList; struct linkedList { double data; linkedList next; }; void insertHead (linkedList l, double data); int lookup (linkedList l, double data);

  21. Linear List (Linked-based) // implementation of “insertHead” 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!

  22. Linear List (Linked-based) // implementation of “lookup” int lookup (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!

  23. Client Code #include “linkedList.h” … linkedList list = newLinkedList (); for (int i=0; i<10; i++) { insertHead (list, 3.14); }

  24. Linear List (Linked-based) // a polymorphic linked list: typedef struct linkedList *linkedList; struct linkedList { void*data; linkedList next; }; void insertHead (linkedList l, void *data); int lookup (linkedList l, void *data);

  25. Linear List (Linked-based) // implementation of “insertHead” void insertHead (linkedList l, void *data) { linkedList temp = malloc (sizeof (*temp)); temp->data = data; temp->next = l->next; l->next = temp; return; }

  26. Linear List (Linked-based) // implementation of “lookup” int lookup (linkedList l, void *data) { linkedList temp = l->next; while (temp) { if (temp->data == data) // Right??? return 1; temp = temp->next; } return 0; }

  27. 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, ???); }

  28. Client Code // 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); }

  29. Client Code // a list of “doubles” #include “linkedList.h” … linkedList list = newLinkedList (); void *p; for (int i=0; i<10; i++) { p = malloc (8); *((double *)p) = 3.14; insertHead (list, p); } // The burden is lifted to user of linkedList!

  30. Pros. and Cons. of Polymorphism • Polymorphism pros: • code reuse: write once, use in arbitrary contexts • ADT: data structures won’t change client data (won’t know) • Polymorphism cons: • Inconsistency (safety issues) • Complexity • Efficiency • We’d discuss cons. issues next

  31. Problem #1: Inconsistency (Safety Issues) #include “linkedList.h” … linkedList list = newLinkedList (); void *p; for (int i=0; i<10; i++){ p = malloc (4); *((int *)p) = i; insertHead (list, p); } double *f = listGetHead (list); // ever worse: int (*p)() = listGetHead (list); (*p) ();

  32. 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 • In C. It’s programmers’ duty to guarantee this! • Important: always keep your data structure invariants in mind!

  33. Problem #2: Complexity // implementation of “lookup” int lookup (linkedList l, void *data) { linkedList temp = l->next; while (temp) { if (temp->data == data) // Right??? return 1; temp = temp->next; } return 0; }

  34. Problem #2: Complexity // Recall the definition of polymorphic variables: void *p, *q; // We want to write a function “equals ()” int equals (void *x, void *y); // How to implement this? x y

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

  36. Problem #2: Complexity // Try #2: int equals (void *x, void *y) { return (*x==*y); // right? } x y

  37. Cure to Problem #2: Extra Comparing Function // Try #2: typedef int (*tyEq) (void *, void *); int equals (void *x, void *y, tyEq eq) { return (eq (x, y)); } x y

  38. Client Code int comp (void *p, void *q){ return (*p==*q); } //////////////////////////////////////// void *x = malloc (4); *x = 9; void *y = malloc (4); *y = 9; equals (x, y, comp);

  39. Client Code int comp (void *p, void *q){ return (p->i==q->i && p->f==q->f); } //////////////////////////////////////// void *x = malloc (sizeof (struct s)); *x = …; void *y = malloc (sizeof (struct s)); *y = …; equals (x, y, comp); // A mimic of so-called “callback”.

  40. Cure to Problem #2: Function Pointers in Data int equals (void *x, void *y) { return (x->eq (x, y)); } x y eq Essential features of OO programming!

  41. 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); }

  42. Boxed Data • Polymorphism does not come free • data must be heap-allocated, to cope with the “void *” pointer convention • makes memory management harder • 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

  43. A Glimpse on Other Forms of Polymorphism // In C void *p; p = malloc (4); *((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)); // Or: 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