1 Getting started
2 Defining equality
3 Alternative approaches: bad and good
3.1 Bad Option - Incorrect alternative:
3.2 Good Option - A Correct alternative:
Version: 5.3.0.10

Lab 5a

Goals:

The goal of this lab is to learn how to define equality of the values of two objects that are instances of a union of classes.

Note: This material is covered in pages 321 - 330 in the textbook. Read it carefully.

1 Getting started

For this part of the lab we will work with classes that define bank accounts: a checking account or a savings account. Download the files Banking.zip that represent this class hierarchy and start a new project. Run the project and read through the examples to make sure what is involved in defining each type of account. Make two more examples of each type of account and add the needed tests for the method amtAvailable in these classes.

2 Defining equality

Our object is to define a method that will determine whether a given Account is the same as this account. We may need such a method to find a desired account within some class that represents the bank and all accounts in it.

Of course, now that we have the abstract class it would be easy to compare just account number and the name on the account, but we want to make sure that all the customer’s data matches what we have on file exactly, including balances, interest rates, etc.

Implementing the same method

We will design the method same similar to the techonque described in the lecture, called equality by safe casting. The relevant examples can be found in the lecture notes. You may want to look at the code there as you work through this problem.

3 Alternative approaches: bad and good

3.1 Bad Option - Incorrect alternative:

The method above can be incorrectly written with two features of the Java language: the instanceof operator and casting. In the Checking class this style method would look like the following:

// Is the given Account the same as this Checking?

boolean same(Account that){

  if(that instanceof Checking){

    return this.sameChecking((Checking)that);

  }else{

    return false;

  }

}

However, this version introduces bugs!

The issue is that any class that later extends Checking, say a PremiumChecking class, will also be considered a Checking instance by the instanceof operator.

If we implement a similar same method in PremiumChecking:

// Is the given Account the same as this PremiumChecking?

boolean same(Account that){

  if(that instanceof PremiumChecking){

    return this.samePremChecking((PremiumChecking)that);

  }else{

    return false;

  }

}

Now only a PremiumChecking object can be the same as the given instance of the PremiumChecking class.

But and instance of the Checking class can be the same as the given instance of the PremiumChecking class!!

These kinds of bugs can cause serious problems. This issue is also illustrated in the example file BadSame.java. Add the file to your project and run the exampleto see where the program fails to provide correct answers.

3.2 Good Option - A Correct alternative:

In the lecture we introduced another version that also works. It requires us to add a new method to the abstract class for each subclass of Account.

For our AShape hierarchy (the classes that extend the abstract class AShape from the earlier lectures, the same method implementation in each class would be similar to the one for the Circle class:

// Is this circle the same as the given shape?

public boolean same(AShape that){

  return that.sameCircle(this);

}

and we would then need to define in the abstract class one such method for every class that extends it (just returning false, and override the appropriate method in the class that extends AShape:

// in the class AShape:

 

// Is that Circle the same as this Shape?

public boolean sameCirc(Circ that){ return false; }

 

// Is that Rect the same as this Shape?

public boolean sameRect(Rect that){ return false; }

 

// Is that Combo the same as this Shape?

public boolean sameCombo(Combo that){ return false; }

 

 

// in the class Circle:

 

// Is that Circle the same as this Shape?

public boolean sameCirc(Circ that){

  ... proper implementation that compares two Circle objects ...

}

This technique is popular in object-oriented languages like Java and is known as double dispatch.