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 CreditCard
s.
Because of substitutability, GlobalCredit
can also contain
RewardCard
s.
instanceof
Substitutability 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 = "--------------------------------------------------";