Time to eliminate the duplicate code you hastily introduced. The only change between getEndDate as defined in CourseSession and SummerCourseSession is the session length. Define a protected method in CourseSession to return this value: public class CourseSession implements Comparable<CourseSession> { ... protected int getSessionLength() { return 16; } ... Change getEndDate to call getSessionLength: public Date getEndDate() { GregorianCalendar calendar = new GregorianCalendar(); calendar.setTime(getStartDate()); final int daysInWeek = 7; final int daysFromFridayToMonday = 3; int numberOfDays = getSessionLength() * daysInWeek - daysFromFridayToMonday; calendar.add(Calendar.DAY_OF_YEAR, numberOfDays); return calendar.getTime(); } In SummerCourseSession, override the method getSessionLength. Summer sessions are 8 weeks, not 16. In this case, overriding is a fine alternative to extending, since you are not changing behavior, only data-related details of the behavior. public class SummerCourseSession extends CourseSession { ... @Override protected int getSessionLength() { return 8; } ... When you override a method, you should precede it with an @Override annotation. You use annotations to mark, or annotate, specific portions of code. Other tools, such as compilers, IDEs, and testing tools, can read and interpret these annotations. The Java compiler is the tool that reads the @Override annotation. The compiler ensures that for a method marked as @Override, a method with the same name and arguments exists in a superclass. If you screwed up somehowperhaps you mistyped the method as getSessionLentgh instead of getSessionLengththe compile fails. You see the message: method does not override a method from its superclass Java does not require you to add @Override annotations to your code. However, they provide valuable documentation for your code as well as protections from simple mistakes. You can read more about annotations in Lesson 15. You may now remove getEndDate from SummerCourseSession. In Figure 6.3, the getSessionLength operation appears twice, an indication that the subclass (SummerCourseSession) overrides the superclass (CourseSession) definition. Note that I have preceded each method with access privilege information, something I rarely do. Since normally I only display public information in a UML sketch, I prefer to omit the + (plus sign) that indicates a publicly accessible operation. Figure 6.3. Overriding a Protected MethodIn this circumstance, however, getSessionLength is protected, not public. Adding the access privilege indicators to the diagram in Figure 6. differentiates access between the methods and highlights the relevancy of getSessionLength. The UML indicator for protected is the pound sign (#).[3]
Most of the logic for determining the end date of a session is fixed. The only variance in the logic between CourseSession and SummerCourseSession is the session length. This variance is represented by the abstraction of a separate method, getSessionLength. The CourseSession class can supply one implementation for getSessionLength, the SummerCourseSession another. The method getEndDate in CourseSession acts as a template. It supplies the bulk of the algorithm for calculating a session end date. Certain pieces of the algorithm are "pluggable," meaning that the details are provided elsewhere. Subclasses can vary these details. The template algorithm in getEndDate is an example of a design pattern known as Template Method.[4]
|