Source: Horstmann lab 11

P1. Inheritance

Consider the following Card class. You can test it with the following driver: CardDriver class.
Use this class as a superclass to implement a hierarchy of related classes:




ID number

Calling Card

Card number, PIN


Expiration year

Write definitions for each of the subclasses. For each subclass, supply private instance variables. Leave the bodies of the constructors and the format methods blank for now. For example, CallingCard. Note that CallingCard does not rewrite the isExpired method, since it is inherited from Card, and it won't be changed. However, DriverLicense is a different matter.

P2. Calling the Superclass Constructor
Implement constructors for each of the three subclasses. Each constructor should call the superclass constructor to set the name. Here is one example: CallingCard and the driver to try it: CardDriver

P3. Overriding Methods

Supply the implementation of the format method for the three subclasses. The methods should produce a formatted description of the card details. The subclass methods should call the superclass format method to get the formatted name of the cardholder. For example, CallingCard and same driver as P2.

P4. Polymorphism

Devise another class, Billfold, which contains slots for two cards, card1 and card2, a method void addCard(Card) and a method String formatCards().

The addCard method checks if card1 is null. If so, it sets card1 to the new card. If not, it checks card2. If both cards are set already, the method has no effect. (In Chapter 13 you will learn how to collect an arbitrary number of items.)

Of course, formatCards invokes the format method on each non-null card and concatenates the resulting strings. This exemplifies polymorphism, since when Billfold calls card.format(), it won't know which format method will run, the one in IDCard or the one in DriverLicense or the one in CallingCard.

Finish off this class: Billfold and try it out with CardDriver

Explain why the output of your program demonstrates polymorphism.

P5. Overriding methods

The Card superclass defines a method isExpired, which always returns false. This method is not appropriate for the driver license. Supply a method DriverLicense.isExpired() in DriverLicense that checks if the driver license is already expired (i.e., the expiration year is less than the current year).
Note, you can get the current year as follows:

import java.util.Calendar ;    // at the top of your program
Calendar calendar = Calendar.getInstance() ;  // in your method
int currentYear = calendar.get(Calendar.YEAR) ;

The ID card and the calling card don't expire. What should you do to reflect this fact in your implementation?

Add a method getExpiredCardCount, which counts the number of expired cards in the billfold, to the Billfold class.

Try it out with CardDriver class that populates a billfold with a phone card and an expired driver license.

P6. toString() methods

Here is a Card class class with a toString method which uses the getClass() method. The purpose of this, rather than hardcoding the name of the class as Card is so that when the subclasses call super.toString() they will get the name of their own class. Add the appropriate toString() method to its three subclasses and try it out with CardDriver class. The methods should print:
the name of the class
the values of all instance fields (including inherited fields)

Typical formats are:
Card[name=Edsger W. Dijkstra]
PhoneCard[name=Bjarne Stroustrup][number=4156646425,pin=2234]

P7. boolean equals(Object other) methods

Here is a Card class class with an equals method which checks that the two card objects have the same type and the same names. Cards are the same if the objects belong to the same class, and if the names and other information (such as the expiration year for driver licenses) match. Here is the way to do it for subclass IDCard. Define similar equals methods for the other two subclasses and try it out with CardDriver class.