slanted W3C logo

Lab 08—eCheck09A Tutorial

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).

The Problem

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.

Before You Start 1

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.

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
      }

Before You Start 2

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?

Before You Start 3

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 = "--------------------------------------------------";

A Test File

Here is the test file that the example uses