Lab: Experimenting with Specialization and Inheritance Lab: Experimenting with Specialization and Inheritance Instructions:Omitted Getting Ready:Omitted 1. Using an Existing Class: In this part of the lab you will get some additional experience using existing classes. Write a driver that constructs two clocks, one for Harrisonburg and one for Paris. What code did you include in your driver? public static void main(String[] args) { Clock home, paris; home = new Clock(); paris = new Clock("Paris"); } Compile and execute your driver to make sure it works. (Note: You may need to move one of the clocks to see the other one.) 2. Extending an Existing Class: This part of the lab will help you understand how to specialize existing classes using inheritance. Create a file named AlarmClock.java that contains the following: AlarmClock1.java
Modify the two constructors in the AlarmClock class so that they call the appropriate constructors in the Clock class. What code did you add? /** * Default Constructor */ public AlarmClock() { super(); } /** * Explicit Value Constructor * * Constructs a clock for a particular city, setting * the time zone appropriately * * @param city The city */ public AlarmClock(String city) { super(city); } Modify your driver so that the clock for Harrisonburg is actually an AlarmClock object. What code did you add? /** * The enty point of the application * * @param args The command line arguments */ public static void main(String[] args) { AlarmCLock home; Clock paris; home = new AlarmClock(); paris = new Clock("Paris"); } Compile and execute your driver. Add the following to your AlarmClock.java class: AlarmClock2.java
and complete the setAlarm() method (i.e., set the attributes appropriately). What code did you add? /** * Set the alarm * * @param hour The hour of the alarm * @param minute The minute of the alarm * @param second The second of the alarm * @param ampm "AM" for before noon, "PM" for noon and after */ public void setAlarm(int hour, int minute, int second, String ampm) { this.hour = hour; this.minute = minute; this.second = second; this.ampm = ampm; } Add the following to your AlarmClock.java class: AlarmClock3.java
and complete the updateTime() method. What code did you add? /** * Update the time displayed on the clock */ public void updateTime() { int hourNow, minuteNow, secondNow; String ampmNow; // Call the parent's version super.updateTime(); // Check if the alarm is on and if the alarm should sound if (on) { hourNow = getHour(); minuteNow = getMinute(); secondNow = getSecond(); ampmNow = getAMPM(); if ((hourNow == hour) && (minuteNow == minute) && (secondNow == second) && ampmNow.equals(ampm)) { beep(); } } } Modify your driver so that it sets the alarm (for a time about a minute in the future) and turns the alarm on. What code did you add? home.setAlarm(1, 39, 45, "PM"); home.turnAlarmOn(); Compile and execute your driver. What happens (or doesn't happen) if you comment out the call to the parent's updateTime() method? The time does not change every second the way it should because that behavior is provided by the updateTime() method in the Clock class. Note that if you called updateTime(); instead of super.updateTime(); you would call the method in the AlarmClock class. In other words, the updateTime() method in the AlarmClock class would call the updateTime() method in the AlarmClock. This is an "infinite recursion" and, ultimately, results in a "stack overflow". 3. Common Problems: In this part of the lab you will think about the extension mechanism in Java and the kinds of errors you might encounter when you develop classes that use this mechanism. Create a file named Tester1.java that contains the following: Tester1.java
Compile Tester1.java. The setup() method has a Clock as a formal parameter but is actually passed an AlarmClock. Why did it compile properly anyway? It compiles because the AlarmClock class extends the Clock class. Hence, an AlarmClock object "is a" Clock. Create a file named Tester2.java that contains the following: Tester2.java
Compile Tester2.java. Why didn't this class compile? It did not compile because the Clock class does not have a turnAlarmOn() method. From the compiler's perspective, clock in the setup() method is a Clock object (and, hence, does not have a turnAlarmOn() method). Create a file named Tester3.java that contains the following: Tester3.java
Compile Tester3.java. Why didn't this class compile? It will not compile because an attempt is made to pass a Clock object (named paris) to a method that is expecting an AlarmClock object. Create a file named Tester4.java that contains the following: Tester4.java
Compile Tester4.java. The createClock() method creates and returns AlarmClock objects that main assigns to Clock objects. Why did this class compile anyway? The createClock method returns an AlarmClock object which is then assigned to a reference variable that is supposed to point to a Clock object. Since an AlarmClock object "is a" Clock this assignment will work. Create a file named Tester5.java that contains the following: Tester5.java
Compile Tester5.java. Why didn't this class compile? In the main() method an attempt is made to call the setAlarm() method that belongs to the home object. However, from the compiler's perspective, home is a Clock object and does not have such a method. You might argue that the home object is actually an AlarmClock since that is how it is created in the createClock() method. However, the compiler is "unaware" of this since it is declared to be a Clock in the main() method. Create a file named Tester6.java that contains the following: Tester6.java
Compile Tester6.java. createClock() returns a Clock that is being typecast as an AlarmClock. Why did this class compile? The compiler has no way to determine whether a typecast is correct or not. Hence, if you explicitly typecast something the compiler will assume that you know what you're doing and allow it. You might argue that the compiler should know that a Clock is being returned because of the return type of the createClock() method. However, the object that is returned could be an AlarmClock (since an AlaramClock "is a" Clock), in which case the typecase would be appropriate. Execute Tester6. What happened? The following exception was thrown: Exception in thread "main" java.lang.ClassCastException: Clock cannot be cast to AlarmClock at Tester6.main(Tester6.java:16) At run-time, Java noticed that an attempt was made to typecast a Clock as an AlarmClock. An exception was thrown to prevent any problems that might result. Create a file named Tester7.java that contains the following: Tester7.java
Compile Tester7.java. createClock() claims to return a Clock but it actually returns an AlarmClock. Why did this class compile? Because an AlarmClock "is a" Clock. Execute Tester7. What happened? It executed properly. Since the object that was returned by createClock() is, actually, an AlarmClock, the typecast did not cause any problems at run-time. Department of Computer Science Copyright 2010