
eCheck09A can be found on pages 363—365 of the textbook.
Before you start, you should open the type.lib.CreditCard,
type.lib.RewardCard, and type.lib.GlobalCredit
APIs in your web browser (in a separate tab or window).
You need to write a Java program that reads in a file that
encodes credit and reward card transactions. The credit and
reward cards are held in a GlobalCredit
collection. The output for
the program is the enumerated list of transactions and the
outcome of the transactions (either done or failed), followed
by the summary of each of reward card, followed by the summary
of each credit card.
The key principle in this exercise is substitutability.
RewardCard extends (or is a child class of, or is a subclass of,
or is a specialization of) CreditCard. This means that a
RewardCard is substitutable for a CreditCard;
the client can use a reference to a RewardCard anywhere a
reference to a CreditCard is needed.
GlobalCredit models a collection of CreditCards.
Because of substitutability, GlobalCredit can also contain
RewardCards.
instanceofSubstitutability lets you treat a RewardCard as if it were a
CreditCard, so you can add a RewardCard to a
GlobalCredit collection.
As far as GlobalCredit is concerned, every card it contains
is a CreditCard. That is why its get method always
returns a reference to a CreditCard, even if the card really is
a RewardCard.
What happens if you want to call a RewardCard method on
a card returned by get? You have to first check that the
card really is a RewardCard, and if it is, cast the
card to a RewardCard.
You check if a card is a RewardCard by using the
instanceof operator:
// assume you have a GlobalCredit collection named gc
// with at least one CreditCard in it
CreditCard cc = gc.getFirst();
if (cc instanceof RewardCard)
{
// cc really is a RewardCard (or a subclass of RewardCard)
// so you can cast cc to a RewardCard
RewardCard rc = (RewardCard) cc;
// use a RewardCard method
int rewardPoints = rc.getPointBalance();
}
else
{
// cc is not a RewardCard
}
The second principle this exercise emphasizes is reading of the APIs. In particular, you need to know what operations with credit and reward cards can fail, and how they might fail.
Issuing a card: Issuing a card requires creating
a CreditCard or RewardCard instance
and adding it to the GlobalCredit collection.
How might this operation fail? How can you tell if this
operation fails?
Charging a card: Charging a card requires retrieving
the specified card from the GlobalCredit collection
and invoking the card's charge method.
How might this operation fail? How can you tell if this
operation fails?
Making a payment on a card: Making a payment on a
card requires retrieving the specified card from the
GlobalCredit collection
and invoking the card's pay method.
How might this operation fail? How can you tell if this
operation fails?
Redeeming all of the reward points: Redeeming all
of the reward points for a RewardCode requires
retrieving the specified card from the
GlobalCredit collection, invoking its
getPointBalance method to find the number
of reward points, and invoking its redeem
method to redeem the points. How might this operation fail?
How can you tell if this operation fails?
Finally, the output formatting for this exercise is under-specified. You can infer the required formatting by repeatedly running your program through eCheck, but this can be frustrating. Here are some hints:
a) There are no tabs in the output.
b) Use printf (from PrintStream)
or format (from String) to format
the output.
c) The transaction number should be output with a width of 4 characters followed by a period followed by 2 spaces.
d) The transaction type should be output with a width of 10 characters (left justified) followed by 3 periods followed by 4 spaces.
e) The string for the 3 horizontal lines is:
final String HRULE = "--------------------------------------------------";