1 / 40

Comp 401 Dynamic Dispatch and Abstract Methods

Comp 401 Dynamic Dispatch and Abstract Methods. Instructor: Prasun Dewan. A StringHistory Implementation. public class AStringHistory implements StringHistory { public static final int MAX_SIZE = 50; String[] contents = new String[MAX_SIZE]; int size = 0;

tolla
Télécharger la présentation

Comp 401 Dynamic Dispatch and Abstract Methods

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. Comp 401Dynamic Dispatch and Abstract Methods Instructor: PrasunDewan

  2. A StringHistory Implementation • public classAStringHistoryimplementsStringHistory { • public staticfinalint MAX_SIZE = 50; • String[] contents = new String[MAX_SIZE]; • int size = 0; • publicint size() { return size;} • public String elementAt (int index) { return contents[index]; } • booleanisFull() { return size == MAX_SIZE; } • publicvoidaddElement(String element) { • if (isFull()) • System.out.println("Adding item to a full history"); • else { • contents[size] = element; • size++; • } • } • }

  3. A Big StringHistory Implementation • public classABigStringHistoryimplementsStringHistory { • public staticfinalint MAX_SIZE = 500; • String[] contents = new String[MAX_SIZE]; • int size = 0; • publicint size() { return size;} • public String elementAt (int index) { return contents[index]; } • booleanisFull() { return size == MAX_SIZE; } • publicvoidaddElement(String element) { • if (isFull()) • System.out.println("Adding item to a full history"); • else { • contents[size] = element; • size++; • } • } • }

  4. Null Overridden Method publicabstractclassAnAbstractStringHistory{ booleanisFull(){}; voiduncheckedAddElement(Object element){}; publicvoidaddElement(Object element) { if (!isFull()) uncheckedAddElement(element); else handleError(); } voidhandleError () { System.out.println("Adding item to a full history"); }; }

  5. A StringHistory Implementation • public classAStringHistoryextends AnAbstractStringHistory • implementsStringHistory { • publicfinalint MAX_SIZE = 50; • String[] contents = new String[MAX_SIZE]; • int size = 0; • publicint size() { return size;} • public String elementAt (int index) { return contents[index]; } • booleanisFull() { return size == MAX_SIZE; } • voiduncheckedAddElement(String element) { • contents[size] = element; • size++; • } • }

  6. Dynamic Dispatch publicabstractclassACollection { booleanisFull(){}; voiduncheckedAddElement(Object element){}; publicvoidaddElement(Object element) { if (!isFull()) uncheckedAddElement(element); else handleError(); } voidhandleError () { System.out.println("Adding item to a full history"); }; } • public classAStringHistoryextends ACollectionimplementsStringHistory { • … • booleanisFull() { return size == MAX_SIZE; } • voiduncheckedAddElement(String element) { • contents[size] = element; • size++; • } • } Which isFull() called when addElement is invoked on an instance of AStringHistory()? Regular method: called method “statically dispatched” at compile time, so overridden isFull() Virtual method: most specific implementation of called method “dynamically dispatched” at execution time, so overriding isFull()

  7. Regular vs. Virtual Method • Smalltalk: had only virtual methods • With each object a table kept which associates method header with most specific implementation. • Table accessed at execution time. • C++: Had both virtual and regular methods • More efficient with regular methods • Java: Has only virtual methods • Abstract and interface method by definition are virtual methods

  8. Correct A Big StringHistory Implementation • public classABigStringHistoryextends AnAbstractStringHistory • implementsStringHistory { • publicfinalint MAX_SIZE = 500; • String[] contents = new String[MAX_SIZE]; • int size = 0; • publicint size() { return size;} • public String elementAt (int index) { return contents[index]; } • booleanisFull() { return size == MAX_SIZE; } • voiduncheckedAddElement(String element) { • contents[size] = element; • size++; • } • }

  9. An Erroneous Big StringHistory Implementation • public classABigStringHistoryextends AnAbstractStringHistory • implementsStringHistory { • publicfinalint MAX_SIZE = 500; • String[] contents = new String[MAX_SIZE]; • int size = 0; • publicint size() { return size;} • public String elementAt (int index) { return contents[index]; } • booleanisFull() { return size == MAX_SIZE; } • //voiduncheckedAddElement(String element) { • // contents[size] = element; • // size++; • //} • }

  10. Null Overridden Method publicabstractclassAnAbstractStringHistory{ booleanisFull(){}; voiduncheckedAddElement(Object element){}; publicvoidaddElement(Object element) { if (!isFull()) uncheckedAddElement(element); else handleError(); } voidhandleError () { System.out.println("Adding item to a full history"); }; }

  11. abstract methods publicabstractclassAnAbstractStringHistory{ abstractbooleanisFull(); abstractvoiduncheckedAddElement(Object element) publicvoidaddElement(Object element) { if (!isFull()) uncheckedAddElement(element); else handleError(); } voidhandleError () { System.out.println("Adding item to a full history"); }; } Only header of method provided as in interface

  12. An Erroneous Big StringHistory Implementation • public classABigStringHistoryimplementsStringHistory { • publicfinalint MAX_SIZE = 500; • String[] contents = new String[MAX_SIZE]; • int size = 0; • publicint size() { return size;} • public String elementAt (int index) { return contents[index]; } • booleanisFull() { return size == MAX_SIZE; } • //voiduncheckedAddElement(String element) { • // contents[size] = element; • // size++; • //} • } Java complains abstract method not implemented in concrete class

  13. Null vs. Abstract Methods publicabstractclassAnAbstractStringHistory{ booleanisFull() {} voiduncheckedAddElement(Object element) {} publicvoidaddElement(Object element) { if (!isFull()) uncheckedAddElement(element); else handleError(); } voidhandleError () { System.out.println("Adding item to a full history"); }; } Null methods could replace abstract methods in this example. Abstract method force overriding implementations in subclasses. Provide better documentation, indicating to programmer that subclass will implement them.

  14. Abstract method • Declared only in abstract classes • Keyword: abstract • No body • Each (direct or indirect) subclass must implement abstract methods defined by an abstract class. • Much like each class must implement the methods defined by its interface(s).

  15. Abstract class vs. methods • Abstract method => containing class abstract • Cannot have an unimplemented method in an instance • Abstract class may not contain abstract method

  16. Abstract Class publicabstractclassAnAbstractStringHistory{ abstractbooleanisFull(); abstractvoiduncheckedAddElement(Object element); publicvoidaddElement(Object element) { if (!isFull()) uncheckedAddElement(element); else handleError(); } voidhandleError () { System.out.println("Adding item to a full history"); }; }

  17. Concrete Class • public classABigStringHistoryextends AnAbstractStringHistory • implementsStringHistory { • publicstaticfinalint MAX_SIZE = 500; • String[] contents = new String[MAX_SIZE]; • int size = 0; • publicint size() { return size;} • public String elementAt (int index) { return contents[index]; } • booleanisFull() { return size == MAX_SIZE; } • voiduncheckedAddElement(String element) { • contents[size] = element; • size++; • } • } Move more code to abstract class?

  18. New Abstract Class • public classAnAbstractStringHistoryimplementsStringHistory { • String[] contents = new String[maxSize()]; • int size = 0; • abstractintmaxSize(); • publicint size() { return size;} • public String elementAt (int index) { return contents[index]; } • booleanisFull() { return size == maxSize(); } • publicvoidaddElement(String element) { • if (isFull()) • System.out.println("Adding item to a full history"); • else { • contents[size] = element; • size++; • } • } • }

  19. New Concrete Class • public classABigStringHistoryextends AnAbstractStringHistory • implementsStringHistory { • publicstaticfinalint MAX_SIZE = 500; • intmaxSize() { • return MAX_SIZE; • } • } Method call needed to access constant

  20. Another Course package courses; publicabstractclassACourse { String title, dept; publicACourse (String theTitle, String theDept) { super(); title = theTitle; dept = theDept; } public String getTitle() { return title; } publicString getDepartment() { return dept; } abstractpublicintgetNumber(); } Abstract Method

  21. Alternative ARegularCourse package courses; publicclassARegularCourseextendsACourse { intcourseNum; publicARegularCourse (String theTitle, String theDept, inttheCourseNum) { super (theTitle, theDept); courseNum = theCourseNum; } publicintgetNumber() { returncourseNum; } } Like interface, force implementation of getNumber() Implementation of abstract method

  22. Alternative AFreshmanSeminar package courses; publicclassAFreshmanSeminarextendsACourse { publicAFreshmanSeminar (String theTitle, String theDept) { super (theTitle, theDept); } publicintgetNumber() { return SEMINAR_NUMBER; } } Implementation of abstract method

  23. Abstract Class publicabstractclassAnAbstractStringHistory{ abstractbooleanisFull(); abstractvoiduncheckedAddElement(Object element); publicvoidaddElement(Object element) { if (!isFull()) uncheckedAddElement(element); else handleError(); } voidhandleError () { System.out.println("Adding item to a full history"); }; } Not public

  24. Factory Abstract Method … abstract <T> <M>(…) ; … extends … <T> <M>(…) { returnnew <C1> (…) } … … <T> <M> (…){ returnnew <C2> (…) } … Abstract method that returns an instance of some type T – like a factory, it creates and initializes an object.

  25. Abstract methods vs. Interfaces • Unimplemented methods become abstract methods to be implemented by concrete subclasses. Do not need explicit implements clause in subclass if no additional public methods implemented, • publicclassARegularCourseextendsACourse { …. } • A class with only abstract methods simulates interfaces. • No multiple inheritance in Java • Separation of abstract and concrete methods with interfaces. • A class implements but does not inherit a specification!

  26. Abstract methods vs. Interfaces • Non-public abstract methods relevant even in Java • All interface methods must be public. • May want non public abstract methods.E.g. • abstractbooleanisFull() ;

  27. Another Course package courses; publicabstractclassACourseimplements Course { String title, dept; publicACourse (String theTitle, String theDept) { super(); title = theTitle; dept = theDept; } public String getTitle() { return title; } publicString getDepartment() { return dept; } } An abstract class can implement any interface This means all sub classes implement the interface Interface implementation check is made for concrete classes

  28. Alternative ARegularCourse package courses; publicclassARegularCourseextendsACourse { intcourseNum; publicARegularCourse (String theTitle, String theDept, inttheCourseNum) { super (theTitle, theDept); courseNum = theCourseNum; } publicintgetNumber() { returncourseNum; } } Saying ARegularCourse implements Course is redundant

  29. Alternative AFreshmanSeminar package courses; publicclassAFreshmanSeminarextendsACourse { publicAFreshmanSeminar (String theTitle, String theDept) { super (theTitle, theDept); } publicintgetNumber() { return SEMINAR_NUMBER; } } No need for implementation clause

  30. Polymorphic method ARegularCourse AFreshmanSeminar getNumber() in ARegularCouse getNumber() in AFreshmanSeminar Dynamically dispatched method Overloaded method Overloading, Polymorphism, and Dynamic dispatch static void print (Course course) { System.out.println( course.getTitle() + " " + course.getDepartment() + course.getNumber() ); } static void print (CourseListcourseList) { … print(course); … }

  31. Overloading, Polymorphism, and Dynamic dispatch • Same method name works on different types. • Overloading • Multiple (static or instance) methods with same name but different parameter types. • Resolved at compile time based on parameter types • Polymorphism • Same method implementation works on multiple object types. • Dynamic dispatch (or virtual methods) • Multiple instance methods with same name in different classes • Resolved at execution time based on type of target object

  32. Polymorphism vs. Overloading and Dynamic Dispatch • Polymorphism vs. Overloading • Polymorphism: single print (Course course) • Overloading: print (ARegularCourse course) and print (AFreshmanSeminar course) with same implementation. • Polymorphism vs. Dynamic Dispatch • Polymorphism: single getTitle() in ACourse • Dynamic dispatch: getTitle() in AFreshmanSeminar() and getTitle() in ARegularCourse() with same implementation. • Create polymorphic code when you can • In overloading and dynamic dispatch, multiple implementations associated with each method name. • In polymorphic case, single implementation. • Use interfaces rather than classes as types of parameters • Use supertypes rather than subtypes as types of parameters

  33. Polymorphism vs. Overloading and Dynamic Dispatch • Cannot always create polymorphic method. • getNumber() for ARegularCourse and AFreshmanSeminar do different things. • print(Course course) and print (CourseListcourseList) do different things. • When polymorphism not possible try overloading and dynamic dispatch.

  34. Manualinstead of Dynamic Dispatch staticvoid print (Course course) { if (course instanceofARegularCourse) number = ((ARegularCourse)course).getCourseNumberRegularCourse (); else if (course instanceofAFreshmanSeminar) number = ((AFreshmanSeminar)course).getCourseNumberFreshmanSeminar (); System.out.println( course.getTitle() + " " + course.getDepartment() + number ); } Must update code as subtypes added More Work

  35. Can we get rid of manual dispatch/instanceof? staticvoid print (Course course) { if (course instanceofRegularCourse) System.out.print(“Regular Course: ”); elseif (course instanceofAFreshmanSeminar) System.out.println(“Freshman Seminar”); System.out.println( course.getTitle() + " " + course.getDepartment() + course.getNumber() ); }

  36. Cannot always get rid of manual dispatch/instancof staticvoid print (Course course) { printHeader (course); System.out.println( course.getTitle() + " " + course.getDepartment() + course.getNumbert() ); } staticvoidprintHeader (ARegularCourse course) { System.out.print(“Regular Course: ”); } staticvoidprintHeader (AFreshmanSeminar course) { System.out.print(“Freshman Seminar: ”); } Actual parameter cannot be supertype of formal parameter At compile time, do not know if regular course or freshman seminar

  37. printHeader() in ARegularCourse package courses; publicclassARegularCourseextendsACourseimplements Course { … publicvoidprintHeader () { System.out.print (“Regular Course: ”) } }

  38. printHeader() in AFreshmanSeminar package courses; publicclassAFreshmanSeminarextendsACourse implements FreshmanSeminar { … publicvoidprintHeader () { System.out.print (“Freshman Seminar: ”) } }

  39. Should not always get rid of manual dispatch/instancof staticvoid print (Course course) { printHeader (course); System.out.println( course.getTitle() + " " + course.getDepartment() + course.getNumbert() ); } staticvoidprintHeader (ARegularCourse course) { System.out.print(“Regular Course: ”); } staticvoidprintHeader (AFreshmanSeminar course) { System.out.print(“Freshman Seminar: ”); } Should not put printHeader() in ARegularCourse or AFreshmanSeminar as it is UI code. Hence need to use instanceof Used in parsers

  40. Extra Slides

More Related