1 / 86

Multiple Inheritance & Factories

Multiple Inheritance & Factories. Prasun Dewan Comp 114. Topics Covered. Multiple inheritance Extending more than one type Factories Class creating objects More on facades Compose objects Can be used independently We use them together here Factory methods

mistico
Download Presentation

Multiple Inheritance & Factories

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. Multiple Inheritance & Factories Prasun Dewan Comp 114

  2. Topics Covered • Multiple inheritance • Extending more than one type • Factories • Class creating objects • More on facades • Compose objects • Can be used independently • We use them together here • Factory methods • Abstract method instead of class

  3. Problem • A modification to the course problem. • Want to gather statistics on how many times a user requested a course • How many times matchTitle() successfully matched a course

  4. Course Interface package courseTree; publicinterface Course extends TreeNode { public String getTitle(); public String getDepartment(); public int getNumber(); publicvoid init (String theTitle, String theDept); }

  5. Logged Course Interface package courseTree; publicinterface LoggedCourse extends Course { publicint getNumberOfQueries(); }

  6. Course abstract class package courseTree; publicabstractclass ACourse implements Course { String title, dept; public ACourse (String theTitle, String theDept) { init (theTitle, theDept); } public ACourse () {} publicvoid init (String theTitle, String theDept) { title = theTitle; dept = theDept; } public String getTitle() {return title;} public String getDepartment() {return dept; } public Course matchTitle(String theTitle) { if ( title.equals(theTitle)) returnthis; elsereturnnull; } }

  7. ALoggedCourse abstract class package courseTree; publicabstract class ALoggedCourse extends ACourse implements LoggedCourse { int numberOfQueries = 0; public ALoggedCourse (String theTitle, String theDept) { super (theTitle, theDept); } public ALoggedCourse () { } publicint getNumberOfQueries() { return numberOfQueries; } publicCourse matchTitle(String theTitle) { Course course = super.matchTitle(theTitle); if (course != null) numberOfQueries++; return course; } }

  8. Regular Course Interface package courseTree; publicinterface RegularCourse extends Course { publicvoidinit (String theTitle, String theDept, int theCourseNum); }

  9. Logged Regular Course Interface package courseTree; publicinterface LoggedRegularCourse extends ??? { … }

  10. Logged Regular Course Interface package courseTree; publicinterface LoggedRegularCourse extends LoggedCourse { publicvoidinit (String theTitle, String theDept, int theCourseNum); } package courseTree; publicinterface LoggedRegularCourse extends RegularCourse { publicint getNumberOfQueries(); }

  11. Duplication package courseTree; publicinterface RegularCourse extends Course { publicvoidinit (String theTitle, String theDept, int theCourseNum); } package courseTree; publicinterface LoggedRegularCourse extends LoggedCourse { publicvoidinit (String theTitle, String theDept, int theCourseNum); }

  12. Duplication package courseTree; publicinterface LoggedCourse extends Course { publicint getNumberOfQueries(); } package courseTree; publicinterface LoggedRegularCourse extends RegularCourse { publicint getNumberOfQueries(); }

  13. Single Interface Inheritance Course publicinterface Course extends TreeNode { public String getTitle(); public String getDepartment(); publicint getNumber(); publicvoidinit (String theTitle, String theDept); } LoggedCourse RegularCourse publicinterface RegularCourse extends Course { publicvoidinit (String theTitle, String theDept, int theCourseNum); } publicinterface LoggedCourse extends Course { publicint getNumberOfQueries(); } LoggedRegularCourse package courseTree; publicinterface LoggedRegularCourse extends LoggedCourse { publicvoidinit (String theTitle, String theDept, int theCourseNum); }

  14. Alternative Single Inheritance Course publicinterface Course extends TreeNode { public String getTitle(); public String getDepartment(); publicint getNumber(); publicvoidinit (String theTitle, String theDept); } LoggedCourse RegularCourse publicinterface RegularCourse extends Course { publicvoidinit (String theTitle, String theDept, int theCourseNum); } publicinterface LoggedCourse extends Course { publicint getNumberOfQueries(); } LoggedRegularCourse package courseTree; publicinterface LoggedRegularCourse extends RegularCourse { publicint getNumberOfQueries(); }

  15. empty interface Multiple Interface Inheritance package courseTree; publicinterface LoggedCourse extends Course { publicint getNumberOfQueries(); } package courseTree; publicinterface RegularCourse extends Course { publicvoidinit (String theTitle, String theDept, int theCourseNum); } package courseTree; publicinterface LoggedRegularCourse extends LoggedCourse, RegularCourse{}

  16. Multiple Interface Inheritance Course publicinterface Course extends TreeNode { public String getTitle(); public String getDepartment(); publicint getNumber(); publicvoidinit (String theTitle, String theDept); } LoggedCourse RegularCourse publicinterface RegularCourse extends Course { publicvoidinit (String theTitle, String theDept, int theCourseNum); } publicinterface LoggedCourse extends Course { publicint getNumberOfQueries(); } LoggedRegularCourse publicinterface LoggedRegularCourse extends RegularCourse {}

  17. Old Regular Course Class publicclass ARegularCourse extends ACourse implements RegularCourse { int courseNum ; public ARegularCourse (String theTitle, String theDept, int theCourseNum) { init (theTitle, theDept, theCourseNum); } public ARegularCourse () {} publicvoidinit (String theTitle, String theDept, int theCourseNum) { super.init (theTitle, theDept); courseNum = theCourseNum; } publicint getNumber() { return courseNum; } }

  18. New Regular Course Class publicclass ALoggedRegularCourse extends ALoggedCourse implements LoggedRegularCourse { int courseNum ; public ALoggedRegularCourse (String theTitle, String theDept, int theCourseNum) { init (theTitle, theDept, theCourseNum); } public ALoggedRegularCourse () {} publicvoidinit (String theTitle, String theDept, int theCourseNum) { super.init (theTitle, theDept); courseNum = theCourseNum; } publicint getNumber() { return courseNum; } } Code duplication and not making sure ALoggedRegularCourse is a ARegularCourse!

  19. Single Class Inheritance ACourse publicclass ACourse implements Course { public String getTitle() {…} public String getDepartment() {…}; publicvoidinit (String theTitle, String theDept) {…}; publicCourse matchTitle (String theTitle) {…}; } ALoggedCourse ARegularCourse publicclass ARegularCourse extends ACourse { publicint getNumber() {…}; publicvoidinit (String theTitle, String theDept, int theCourseNum); } publicclass ALoggedCourse extends ACourse { publicint getNumberOfQueries() {…}; publicCourse matchTitle (String theTitle) {…}; } ALoggedRegularCourse publicinterface LoggedRegularCourse extends ALoggedCourse { publicint getNumber() {…}; publicvoidinit (String theTitle, String theDept, int theCourseNum) {…}; }

  20. Multiple Class Inheritance? ACourse publicclass ACourse implements Course { public String getTitle() {…} public String getDepartment() {…}; publicvoidinit (String theTitle, String theDept) {…}; publicCourse matchTitle (String theTitle) {…}; } ALoggedCourse ARegularCourse publicclass ARegularCourse extends ACourse { publicint getNumber() {…}; publicvoidinit (String theTitle, String theDept, int theCourseNum); } publicclass ALoggedCourse extends ACourse { publicint getNumberOfQueries() {…}; publicCourse matchTitle (String theTitle) {…}; } ALoggedRegularCourse publicclass LoggedRegularCourse extends ALoggedCourse, ARegularCourse { }

  21. Multiple Class Inheritance? publicclass ALoggedRegularCourse extends ALoggedCourse, ARegularCourse implements LoggedRegularCourse {} publicabstract class ALoggedCourse extends ACourse implements LoggedCourse { … publicCourse matchTitle(String theTitle) { Course course = super.matchTitle(theTitle); if (course != null) numberOfQueries++; return course; } } publicclass ARegularCourse extends ACourse implements RegularCourse {…} publicabstractclass ACourse implements Course { … public Course matchTitle(String theTitle) { if ( title.equals(theTitle)) returnthis; elsereturnnull; } } Two different implementations with same header inherited

  22. Multiple inheritance rules • Allow interfaces to inherit multiple times • Only headers are inherited • Do not allow classes to inherit multiple times (Java) • Could inherit multiple bodies with same header • Can be confusing to programmers • Other solutions • Allow multiple inheritance if ambiguity does not arise • If ambiguity arises indicate which implementation is used (C++) • ALoggedCourse.matchTitle() vs ARegularCourse.matchTitle() • Choose one or none of the bodies if problem arises • Based on order in extends clause? • extends ALoggedCourse, ARegularCourse

  23. Multiple Interface Inheritance Course publicinterface Course extends TreeNode { public String getTitle(); public String getDepartment(); publicint getNumber(); publicvoidinit (String theTitle, String theDept); } LoggedCourse RegularCourse publicinterface RegularCourse extends Course { publicvoidinit (String theTitle, String theDept, int theCourseNum); } publicinterface LoggedCourse extends Course { publicint getNumberOfQueries(); } LoggedRegularCourse publicinterface LoggedRegularCourse extends RegularCourse, LoggedCourse{ } Same method headers added twice, no problem

  24. Multiple Interface Inheritance Course publicinterface Course extends TreeNode { public String getTitle(); public String getDepartment(); publicint getNumber(); publicvoidinit (String theTitle, String theDept); } LoggedCourse RegularCourse publicinterface RegularCourse extends Course { publicvoidinit (String theTitle, String theDept, int theCourseNum); } publicinterface LoggedCourse extends Course { publicint getNumberOfQueries(); publicvoidinit (String theTitle, String theDept); } LoggedRegularCourse publicinterface LoggedRegularCourse extends RegularCourse, LoggedCourse { } Interface: set of method headers Addition: removes duplicates Equal method headers inherited twice

  25. Multiple Interface Inheritance Course publicinterface Course extends TreeNode { public String getTitle(); public String getDepartment(); publicint getNumber(); publicvoidinit (String theTitle, String theDept); } LoggedCourse RegularCourse publicinterface RegularCourse extends Course { publicvoidinit (String theTitle, String theDept, int theCourseNum); } publicinterface LoggedCourse extends Course { publicint getNumberOfQueries(); public LoggedCourse init (String theTitle, String theDept); } LoggedRegularCourse publicinterface LoggedRegularCourse extends RegularCourse, LoggedCourse { } Overloading ambiguity, multiple inheritance not allowed Method headers differ only in return type

  26. Classes as types Interfaces as types Single inheritance => reduced polymorphsism? publicclass ALoggedRegularCourse extends ALoggedCourse implements LoggedRegularCourse { … } Code Duplication & ALoggedRegularCourse is not ARegularCourse! void print (ARegularCourse course) {…} ALoggedRegularCourse introProg = new ALoggedRegularRegularCourse(); …. print(introProg); void print (RegularCourse course) {…} LoggedRegularCourse introProg = new ALoggedRegularRegularCourse(); …. print(introProg);

  27. Single inheritance => reduced polymorphism? • Yes, if classes used to type variables • Interfaces offer solution to lack of multiple (class) inheritance in Java • Most programmers do not realise other uses. • In text books, interfaces introduced and used only in problems requiring multiple inheritance

  28. Implementing Single Interface publicclass ALoggedRegularCourse extends ALoggedCourse implements LoggedRegularCourse { int courseNum ; public ALoggedRegularCourse (String theTitle, String theDept, int theCourseNum) { init (theTitle, theDept, theCourseNum); } public ALoggedRegularCourse () {} publicvoidinit (String theTitle, String theDept, int theCourseNum) { super.init (theTitle, theDept); courseNum = theCourseNum; } publicint getNumber() { return courseNum; } } package courseTree; publicinterface LoggedRegularCourse extends LoggedCourse, RegularCourse{}

  29. Implementing Multiple Interfaces publicclass ALoggedRegularCourse extends ALoggedCourse implements LoggedCourse, RegularCourse { int courseNum ; public ALoggedRegularCourse (String theTitle, String theDept, int theCourseNum) { init (theTitle, theDept, theCourseNum); } public ALoggedRegularCourse () {} publicvoidinit (String theTitle, String theDept, int theCourseNum) { super.init (theTitle, theDept); courseNum = theCourseNum; } publicint getNumber() { return courseNum; } }

  30. Multiple interfaces => Casting publicclass ALoggedRegularCourse extends ALoggedCourse implements LoggedCourse, RegularCourse { …. } void print (RegularCourse course) {…} void appendToLog (LoggedCourse course) {…} LoggedCourse introProg = new ALoggedRegularRegularCourse(); …. print((RegularCourse)introProg); …. appendToLog(introProg); RegularCourse introProg = new ALoggedRegularRegularCourse(); …. print(introProg); …. appendToLog((LoggedCourse)introProg);

  31. Single interface publicclass ALoggedRegularCourse extends ALoggedCourse implements LoggedRegularCourse { …. } void print (RegularCourse course) {…} void appendToLog (LoggedCourse course) {…} LoggedregularCourse introProg = new ALoggedRegularRegularCourse(); …. print (introProg); …. appendToLog(introProg);

  32. Single interface and overloading publicclass ALoggedRegularCourse extends ALoggedCourse implements LoggedRegularCourse { …. } void print (RegularCourse course) {…} void print (LoggedCourse course) {…} LoggedRegularCourse introProg = new ALoggedRegularRegularCourse(); …. print ((RegularCourse)introProg); …. appendToLog((LoggedCourse)introProg);

  33. Different interfaces evolved independently TreeNode, LeafOnly, CompositeOnly LoggedCourse, RegularCourse Uniting them creates empty interface Does not require casting to use different interfaces of same object Modulo overloading problems These arise whenever an object can be typed in multiple ways. A compile time issue – these casts are needed only at compile time and do not lead to runtime errors. Implementing multiple interfaces vs. Single Interface

  34. Switching between different course configurations • Want both logged and non-logged versions based on users • Logged course has overhead • Some university may decide logging gives misleading /useless information • How to write programs that can easily switch between the two kinds of courses

  35. ACourseList Using interfaces as types Oblivious to actual classes package courseTree; publicclass ACourseList implements CourseList, TreeNode { final int MAX_SIZE = 50; TreeNode[] contents = new TreeNode[MAX_SIZE]; int size = 0; publicint size() {return size;} public TreeNode elementAt (int index) {return contents[index];} boolean isFull() { return size == MAX_SIZE;} publicvoid addElement(TreeNode element) { if (isFull()) System.out.println("Adding item to a full collection"); else { contents[size] = element; size++; } } public Course matchTitle (String theTitle) { for (int courseIndex = 0; courseIndex < size; courseIndex++) { Course course = contents[courseIndex].matchTitle(theTitle); if ( course != null) return course; } returnnull; } }

  36. Main Class package main; … publicclass ACourseDisplayer { static CourseList courses = new ACourseList(); public static void main(String[] args) { fillCourses(); //Do I/O … } ... staticvoid fillCourses() { CourseList prog = new ACourseList(); prog.addElement (new ARegularCourse ("Intro. Prog.", "COMP", 14)); prog.addElement (new ARegularCourse ("Found. of Prog.", "COMP", 114)); courses.addElement(prog); courses.addElement (new AFreshmanSeminar("Comp. Animation", "COMP")); courses.addElement (new AFreshmanSeminar("Lego Robots", "COMP")); } }

  37. Code Duplication package main; … publicclass ACourseDisplayer { static CourseList courses = new ACourseList(); public static void main(String[] args) { fillCourses(); //Do I/O … } ... staticvoid fillCourses() { CourseList prog = new ACourseList(); prog.addElement (new ALoggedRegularCourse ("Intro. Prog.", "COMP", 14)); prog.addElement (new ALoggedRegularCourse ("Found. of Prog.", "COMP", 114)); courses.addElement(prog); courses.addElement (new ALoggedFreshmanSeminar("Comp. Animation", "COMP")); courses.addElement (new ALoggedFreshmanSeminar("Lego Robots", "COMP")); } }

  38. Code Inconsistency package main; … publicclass ACourseDisplayer { static CourseList courses = new ACourseList(); public static void main(String[] args) { fillCourses(); //Do I/O … } ... staticvoid fillCourses() { CourseList prog = new ACourseList(); prog.addElement (new ALoggedRegularCourse ("Intro. Prog.", "COMP", 14)); prog.addElement (new ALoggedRegularCourse ("Found. of Prog.", "COMP", 114)); courses.addElement(prog); courses.addElement (new AFreshmanSeminar("Comp. Animation", "COMP")); courses.addElement (new AFreshmanSeminar("Lego Robots", "COMP")); } } Adding logged regular course and unlogged freshman seminar

  39. Switching between classes • How to make main and other classes instantiating course objects oblivious to which course set is used? • How to make sure incompatible courses are not added to course list • AFreshmanSeminar • ALoggedRegularCourse

  40. Factory class • Creates a set of related objects • Different factory classes for different configurations • ACourseFactory • ALoggedCourseFactory • Factory classes providing alternative configurations implement the same interface • CourseFactory

  41. Common Factory Interface package factories; import courseTree.RegularCourse; import courseTree.FreshmanSeminar; publicinterface CourseFactory { public RegularCourse getRegularCourse(); public FreshmanSeminar getFreshmanSeminar(); }

  42. Parameterless constructors ACourseFactory package factories; import courseTree.RegularCourse; import courseTree.FreshmanSeminar; import courseTree.ARegularCourse; import courseTree.AFreshmanSeminar; publicclass ACourseFactory implements CourseFactory { public RegularCourse getRegularCourse() { returnnew ARegularCourse(); } public FreshmanSeminar getFreshmanSeminar() { returnnew AFreshmanSeminar(); } } Factory user will call init()

  43. ALoggedCourseFactory package factories; import courseTree.RegularCourse; import courseTree.FreshmanSeminar; import courseTree.ALoggedRegularCourse; import courseTree.ALoggedFreshmanSeminar; publicclass ALoggedCourseFactory implements CourseFactory{ public RegularCourse getRegularCourse() { returnnew ALoggedRegularCourse(); } public FreshmanSeminar getFreshmanSeminar() { returnnew ALoggedFreshmanSeminar(); } }

  44. Original Main Class package main; … publicclass ACourseDisplayer { static CourseList courses = new ACourseList(); publicstaticvoid main(String[] args) { fillCourses(); //Do I/O … } ... staticvoid fillCourses() { CourseList prog = new ACourseList(); prog.addElement (new ARegularCourse ("Intro. Prog.", "COMP", 14)); prog.addElement (new ARegularCourse ("Found. of Prog.", "COMP", 114)); … } }

  45. New Main Class package main; … publicclass AFactoryBasedCourseDisplayer { static CourseList courses = new ACourseList(); public static void main(String[] args) { fillCourses(); //Do I/O … } ... staticvoid fillCourses() { CourseFactory courseFactory = new ACourseFactory(); CourseList prog = new ACourseList(); RegularCourse introProg = courseFactory.getRegularCourse (); introProg.init("Intro. Prog.", "COMP", 14); RegularCourse foundProg = courseFactory.getRegularCourse (); foundProg.init(“Found. Prog.", "COMP", 114); … } }

  46. New Main Class for logged courses package main; … publicclass AFactoryBasedCourseDisplayer { static CourseList courses = new ACourseList(); public static void main(String[] args) { fillCourses(); //Do I/O … } ... staticvoid fillCourses() { CourseFactory courseFactory = new ALoggedCourseFactory(); CourseList prog = new ACourseList(); RegularCourse introProg = courseFactory.getRegularCourse (); introProg.init("Intro. Prog.", "COMP", 14); RegularCourse foundProg = courseFactory.getRegularCourse (); foundProg.init(“Found. Prog.", "COMP", 114); … } }

  47. Factory Transparent Main? • Same main and other course users for different configurations? • Need FactorySelector Class • Only class changed to select different configurations • Main and other classes call factory selector class

  48. Factory Selector Interface package factories; publicinterface CourseFactorySelector { public CourseFactory getCourseFactory(); }

  49. Factory Selector Class package factories; publicclass ACourseFactorySelector implements CourseFactorySelector { public CourseFactory getCourseFactory() { //returnnew ACourseFactory(); returnnew ALoggedCourseFactory(); } }

  50. Main Class with Factory Selector package main; … publicclass AFactoryBasedCourseDisplayer { static CourseList courses = new ACourseList(); public static void main(String[] args) { fillCourses(); //Do I/O … } ... staticvoid fillCourses() { CourseFactory courseFactory = (new CourseFactorySelector()).getCourseFactory(); CourseList prog = new ACourseList(); RegularCourse introProg = courseFactory.getRegularCourse (); introProg.init("Intro. Prog.", "COMP", 14); RegularCourse foundProg = courseFactory.getRegularCourse (); foundProg.init(“Found. Prog.", "COMP", 114); … } }

More Related