comp 401 dynamic dispatch and abstract methods

40
COMP 401 DYNAMIC DISPATCH AND ABSTRACT METHODS Instructor: Prasun Dewan

Upload: tolla

Post on 22-Feb-2016

29 views

Category:

Documents


0 download

DESCRIPTION

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; - PowerPoint PPT Presentation

TRANSCRIPT

Slide 1

Comp 401Dynamic Dispatch and Abstract Methods

Instructor: Prasun Dewan

#A StringHistory Implementationpublic class AStringHistory implements StringHistory { public static final int MAX_SIZE = 50; String[] contents = new String[MAX_SIZE]; int size = 0; public int size() { return size;} public String elementAt (int index) { return contents[index]; } boolean isFull() { return size == MAX_SIZE; } public void addElement(String element) { if (isFull()) System.out.println("Adding item to a full history"); else { contents[size] = element; size++;} } }

#A Big StringHistory Implementationpublic class ABigStringHistory implements StringHistory { public static final int MAX_SIZE = 500; String[] contents = new String[MAX_SIZE]; int size = 0; public int size() { return size;} public String elementAt (int index) { return contents[index]; } boolean isFull() { return size == MAX_SIZE; } public void addElement(String element) { if (isFull()) System.out.println("Adding item to a full history"); else { contents[size] = element; size++;} } }

#Null Overridden Methodpublic abstract class AnAbstractStringHistory {boolean isFull(){};void uncheckedAddElement(Object element){};public void addElement(Object element) {if (!isFull())uncheckedAddElement(element);elsehandleError();}void handleError () {System.out.println("Adding item to a full history");};}

#4A StringHistory Implementationpublic class AStringHistory extends AnAbstractStringHistory implements StringHistory { public final int MAX_SIZE = 50; String[] contents = new String[MAX_SIZE]; int size = 0; public int size() { return size;} public String elementAt (int index) { return contents[index]; } boolean isFull() { return size == MAX_SIZE; } void uncheckedAddElement(String element) { contents[size] = element; size++;} }

#Dynamic Dispatchpublic abstract class ACollection {boolean isFull(){};void uncheckedAddElement(Object element){};public void addElement(Object element) {if (!isFull())uncheckedAddElement(element);elsehandleError();}void handleError () {System.out.println("Adding item to a full history");};}public class AStringHistory extends ACollection implements StringHistory { boolean isFull() { return size == MAX_SIZE; } void uncheckedAddElement(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()

#6Regular vs. Virtual MethodSmalltalk: had only virtual methodsWith each object a table kept which associates method header with most specific implementation.Table accessed at execution time.C++: Had both virtual and regular methodsMore efficient with regular methodsJava: Has only virtual methodsAbstract and interface method by definition are virtual methods

#Correct A Big StringHistory Implementationpublic class ABigStringHistory extends AnAbstractStringHistory implements StringHistory { public final int MAX_SIZE = 500; String[] contents = new String[MAX_SIZE]; int size = 0; public int size() { return size;} public String elementAt (int index) { return contents[index]; } boolean isFull() { return size == MAX_SIZE; } void uncheckedAddElement(String element) { contents[size] = element; size++;} }

#An Erroneous Big StringHistory Implementationpublic class ABigStringHistory extends AnAbstractStringHistory implements StringHistory { public final int MAX_SIZE = 500; String[] contents = new String[MAX_SIZE]; int size = 0; public int size() { return size;} public String elementAt (int index) { return contents[index]; } boolean isFull() { return size == MAX_SIZE; } //void uncheckedAddElement(String element) { // contents[size] = element; // size++; //} }

#Null Overridden Methodpublic abstract class AnAbstractStringHistory {boolean isFull(){};void uncheckedAddElement(Object element){};public void addElement(Object element) {if (!isFull())uncheckedAddElement(element);elsehandleError();}void handleError () {System.out.println("Adding item to a full history");};}

#10abstract methodspublic abstract class AnAbstractStringHistory {abstract boolean isFull();abstract void uncheckedAddElement(Object element)public void addElement(Object element) {if (!isFull())uncheckedAddElement(element);elsehandleError();}void handleError () {System.out.println("Adding item to a full history");};}Only header of method provided as in interface

#11An Erroneous Big StringHistory Implementationpublic class ABigStringHistory implements StringHistory { public final int MAX_SIZE = 500; String[] contents = new String[MAX_SIZE]; int size = 0; public int size() { return size;} public String elementAt (int index) { return contents[index]; } boolean isFull() { return size == MAX_SIZE; } //void uncheckedAddElement(String element) { // contents[size] = element; // size++; //} }Java complains abstract method not implemented in concrete class

#Null vs. Abstract Methodspublic abstract class AnAbstractStringHistory {boolean isFull() {}void uncheckedAddElement(Object element) {}public void addElement(Object element) {if (!isFull())uncheckedAddElement(element);elsehandleError();}void handleError () {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.

#13Abstract methodDeclared only in abstract classesKeyword: abstractNo bodyEach (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).

#14Abstract class vs. methodsAbstract method => containing class abstractCannot have an unimplemented method in an instanceAbstract class may not contain abstract method

#15Abstract Classpublic abstract class AnAbstractStringHistory {abstract boolean isFull();abstract void uncheckedAddElement(Object element);public void addElement(Object element) {if (!isFull())uncheckedAddElement(element);elsehandleError();}void handleError () {System.out.println("Adding item to a full history");};}

#16Concrete Classpublic class ABigStringHistory extends AnAbstractStringHistory implements StringHistory { public static final int MAX_SIZE = 500; String[] contents = new String[MAX_SIZE]; int size = 0; public int size() { return size;} public String elementAt (int index) { return contents[index]; } boolean isFull() { return size == MAX_SIZE; } void uncheckedAddElement(String element) { contents[size] = element; size++;} }Move more code to abstract class?

#New Abstract Classpublic class AnAbstractStringHistory implements StringHistory { String[] contents = new String[maxSize()]; int size = 0; abstract int maxSize(); public int size() { return size;} public String elementAt (int index) { return contents[index]; } boolean isFull() { return size == maxSize(); } public void addElement(String element) { if (isFull()) System.out.println("Adding item to a full history"); else { contents[size] = element; size++;} } }

#public class ABigStringHistory extends AnAbstractStringHistory implements StringHistory { public static final int MAX_SIZE = 500; int maxSize() { return MAX_SIZE; }}New Concrete ClassMethod call needed to access constant

#Another Coursepackage courses;public abstract class ACourse {String title, dept;public ACourse (String theTitle, String theDept) {super();title = theTitle;dept = theDept;}public String getTitle() {return title;} public String getDepartment() {return dept;}abstract public int getNumber();}Abstract Method

#Alternative ARegularCoursepackage courses;public class ARegularCourse extends ACourse {int courseNum;public ARegularCourse (String theTitle, String theDept, int theCourseNum) {super (theTitle, theDept);courseNum = theCourseNum;} public int getNumber() {return courseNum;}}Implementation of abstract methodLike interface, force implementation of getNumber()

#21Alternative AFreshmanSeminarpackage courses;public class AFreshmanSeminar extends ACourse {public AFreshmanSeminar (String theTitle, String theDept) {super (theTitle, theDept);}public int getNumber() {return SEMINAR_NUMBER;}}Implementation of abstract method

#22Abstract Classpublic abstract class AnAbstractStringHistory {abstract boolean isFull();abstract void uncheckedAddElement(Object element);public void addElement(Object element) {if (!isFull())uncheckedAddElement(element);elsehandleError();}void handleError () {System.out.println("Adding item to a full history");};}Not public

#23Factory Abstract Methodabstract () ; () { return new ()}extends (){ return new ()}Abstract method that returns an instance of some type T like a factory, it creates and initializes an object.

#24Abstract methods vs. InterfacesUnimplemented methods become abstract methods to be implemented by concrete subclasses. Do not need explicit implements clause in subclass if no additional public methods implemented,public class ARegularCourse extends ACourse { . }

A class with only abstract methods simulates interfaces.No multiple inheritance in JavaSeparation of abstract and concrete methods with interfaces.A class implements but does not inherit a specification!

#25Abstract methods vs. InterfacesNon-public abstract methods relevant even in JavaAll interface methods must be public.May want non public abstract methods.E.g. abstract boolean isFull() ;

#26Another Coursepackage courses;public abstract class ACourse implements Course {String title, dept;public ACourse (String theTitle, String theDept) {super();title = theTitle;dept = theDept;}public String getTitle() {return title;} public String getDepartment() {return dept;}}An abstract class can implement any interfaceThis means all sub classes implement the interfaceInterface implementation check is made for concrete classes

#Alternative ARegularCoursepackage courses;public class ARegularCourse extends ACourse {int courseNum;public ARegularCourse (String theTitle, String theDept, int theCourseNum) {super (theTitle, theDept);courseNum = theCourseNum;} public int getNumber() {return courseNum;}}Saying ARegularCourse implements Course is redundant

#28Alternative AFreshmanSeminarpackage courses;public class AFreshmanSeminar extends ACourse {public AFreshmanSeminar (String theTitle, String theDept) {super (theTitle, theDept);}public int getNumber() {return SEMINAR_NUMBER;}}No need for implementation clause

#29Overloading, Polymorphism, and Dynamic dispatch static void print (Course course) {System.out.println( course.getTitle() + "" + course.getDepartment() + course.getNumber() );}static void print (CourseList courseList) {print(course);}Overloaded methodDynamically dispatched methodgetNumber() in ARegularCousegetNumber() in AFreshmanSeminarARegularCourseAFreshmanSeminarPolymorphic method

#30Overloading, Polymorphism, and Dynamic dispatchSame method name works on different types.OverloadingMultiple (static or instance) methods with same name but different parameter types.Resolved at compile time based on parameter typesPolymorphismSame method implementation works on multiple object types.Dynamic dispatch (or virtual methods)Multiple instance methods with same name in different classesResolved at execution time based on type of target object

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

#32Polymorphism vs. Overloading and Dynamic DispatchCannot always create polymorphic method.getNumber() for ARegularCourse and AFreshmanSeminar do different things.print(Course course) and print (CourseList courseList) do different things.When polymorphism not possible try overloading and dynamic dispatch.

#33Manual instead of Dynamic Dispatchstatic void print (Course course) { if (course instanceof ARegularCourse)number = ((ARegularCourse)course).getCourseNumberRegularCourse (); else if (course instanceof AFreshmanSeminar)number = ((AFreshmanSeminar)course).getCourseNumberFreshmanSeminar (); System.out.println(course.getTitle() + "" +course.getDepartment() + number ); }More WorkMust update code as subtypes added

#34Can we get rid of manual dispatch/instanceof?static void print (Course course) { if (course instanceof RegularCourse) System.out.print(Regular Course: ); else if (course instanceof AFreshmanSeminar) System.out.println(Freshman Seminar); System.out.println(course.getTitle() + "" +course.getDepartment() +course.getNumber() );}

#35Cannot always get rid of manual dispatch/instancofstatic void print (Course course) { printHeader (course); System.out.println(course.getTitle() + "" +course.getDepartment() +course.getNumbert() );}static void printHeader (ARegularCourse course) {System.out.print(Regular Course: );}static void printHeader (AFreshmanSeminar course) {System.out.print(Freshman Seminar: );}

At compile time, do not know if regular course or freshman seminarActual parameter cannot be supertype of formal parameter

#36printHeader() in ARegularCoursepackage courses;public class ARegularCourse extends ACourse implements Course {public void printHeader () { System.out.print (Regular Course: ) }}

#37printHeader() in AFreshmanSeminarpackage courses;public class AFreshmanSeminar extends ACourse implements FreshmanSeminar {public void printHeader () { System.out.print (Freshman Seminar: ) }}

#38static void print (Course course) { printHeader (course); System.out.println(course.getTitle() + "" +course.getDepartment() +course.getNumbert() );}static void printHeader (ARegularCourse course) {System.out.print(Regular Course: );}static void printHeader (AFreshmanSeminar course) {System.out.print(Freshman Seminar: );}

Should not always get rid of manual dispatch/instancofShould not put printHeader() in ARegularCourse or AFreshmanSeminar as it is UI code.Hence need to use instanceofUsed in parsers

#39Extra Slides

#