Laboratory: Inheritance
 CSC 207 Algorithms and Object Oriented Design Spring 2011

Summary: In this lab, you will explore inheritance in Java by building and extending some simple classes.

Preparation

1. Create a directory for this lab:
`  mkdir somewhere/inheritance`
2. Go to your new directory:
`  cd somewhere/inheritance`
3. Copy the files for this lab to your new directory:
```  cp ~weinman/public_html/courses/CSC207/2011S/labs/code/inheritance/WhatCounts.java .
cp ~weinman/public_html/courses/CSC207/2011S/labs/code/inheritance/WhatElseCounts.java .```

Exercises

Exercise 1

To start, we will create an interface called `Counter` that specifies capabilities of objects that count things, starting at some value.

The interface should contain three public methods:

Exercise 2

Because different counters might handle their incrementing differently (e.g. arithmetically versus geometrically), but all likely need to track a count and starting value, we can root a class hierarchy with an abstract base class.

Create a new abstract class, `AbstractCounter`, that implements the `Counter` interface and contains:

• Two `int` fields called `count` and `start`. (These should be visible to derived classes, but nothing else.)
• One constructor that takes a starting value as a parameter. The constructor should initialize both `count` and `start` to that value;
• Implementations of:
• `reset()`, which resets `count` to `start`;
• `value()`, which returns the value of `count`

Exercise 3

Finally, we want a concrete version of a counter that simply counts in the usual fashion, by adding one to the count with each increment operation.

1. Create a new concrete class, `BasicCounter` that extends `AbstractCounter`. It should have:
• One constructor that takes a starting value as a parameter. Use `super` to call the instructor of the parent class.
• An implementation of `increment()` that adds 1 to `count`.
2. Inspect the class `WhatCounts.java` that you copied in the lab preparations. What output do you expect?
3. Verify your answer by compiling and running `WhatCounts`.
4. Change the declaration of `alpha` in `WhatCounts.java` so that it reads:
``Counter alpha = new AbstractCounter(0);``
5. What effect to you expect this change to have? Confirm or refute your answer experimentally.
6. Restore the initialization of `alpha` to a `BasicCounter`.

Exercise 4

1. Create a new derived class, `DecrementableCounter`, that has the following form:
DecrementableCounter.java
``````/**
* A Counter that supports decrementing.
*
* @author YOUR NAME HERE
*/
public class DecrementableCounter
extends BasicCounter
{

/**
* Create a new decrementable counter starting from the specified value.
*
* @param start Specified value for this counter to start counting from
*/
public DecrementableCounter(int start)
{
super(start);
} // DecrementableCounter(int)

} // class DecrementableCounter``````
2. Change the initialization of `gamma` in `WhatCounts.java` so that it reads
``Counter gamma = new DecrementableCounter(-5);``
3. What effect to you expect this change to have? Confirm or refute your answer experimentally.
4. Change the initialization of `gamma` so that it reads
``DecrementableCounter gamma = new Counter(-5);``
5. What effect to you expect this change to have? Confirm or refute your answer experimentally.
6. Restore the initialization of `gamma` to
``Counter gamma = new DecrementableCounter(-5);``
7. Add a `decrement()` method to `DecrementableCounter` This method should subtract one from the `count` field.
8. Add lines to `WhatCounts` to test that method.

Exercise 5

1. Create a new class, `LimitedCounter`, that has the following form
LimitedCounter.java
``````/**
* A Counter whose count has an upper bound.
*
* @author YOUR NAME HERE
*/
public class LimitedCounter
extends BasicCounter
{
int limit; /** Limit for this counter */

/**
* Create a new limited counter having the limit and starting
* from the specified value.
*
* @param start Specified value for this counter to start counting from
* @param limit Specified limit for this counter
*/
public LimitedCounter(int start, int limit)
{
super(start);
this.limit = limit;
} // LimitedCounter(int, int)
} // class LimitedCounter ``````
2. Override the `increment` method so that it throws an `IllegalStateException` when `count` exceeds limit.
3. Update `WhatCounts` so that the initialization of `alpha` reads
``Counter alpha = new LimitedCounter(0);``
4. What effect do you expect this change to have? Confirm or refute your prediction experimentally.
5. Determine the results of changing the initialization of `alpha` to
``Counter alpha = new LimitedCounter(-5,3);``
6. Run your current version of `WhatCounts`.
7. Swap the two lines in the constructor for `LimitedCounter` and determine what errors, if any, you get. Why do you think that is?
8. Restore the constructor.

Exercise 6

1. Create a new class, `DoubleCounter`, that has the following form:
DoubleCounter.java
``````public class DoubleCounter
extends BasicCounter
{

} // class DoubleCounter ``````
2. Compile your new class. What error messages, if any, do you receive? If you do not understand the results, check the notes for this exercise.
3. Insert a constructor for `DoubleCounter` of the following form
``````  public DoubleCounter(int start)
{
super(start);
} // DoubleCounter(int)``````
4. Update `WhatCounts` so that the initialization of `beta` reads
``Counter beta = new DoubleCounter(123);``
5. What effect do you expect this change to have? Confirm or refute your prediction experimentally.
6. Override the `increment` method by inserting the following code into `DoubleCounter`
``````  public void increment()
throws IllegalStateException
{
super.increment();
super.increment();
}``````
7. What effect do you expect this change to have in `WhatCounts`? Confirm or refute your prediction experimentally.

Exercise 7

1. Make `LimitedCounter` a subclass of `DoubleCounter` rather than a subclass of `Counter`. (That is, change the line that reads `extends Counter` to read `extends DoubleCounter`.)
2. What effect, if any, do you expect that change to have? Confirm or refute your results experimentally.

Exercise 8

1. Inspect the class `WhatElseCounts.java` that you copied in the lab preparations. What output do you expect?
2. Confirm or refute your hypothesis experimentally by compiling and running `WhatElseCounts`. Can you generalize the pattern?

If you are having trouble, the notes on this exercise gives some background.

Exercise Notes

Notes on Exercise 4

Until you write a constructor for a class, Java implicitly provides a no-argument constructor. The consequence is that all member fields are constructed with their default values (e.g., zero, `false`, or `null`). Once you write a constructor, however, this default constructor is no longer available.

Similarly, unless there is an explicit call to the base class's constructor, each constructor of a derived class will begin with an implicit call to `super()`, the base class's no-argument constructor. If this constructor does not exist, the compiler generates an error.

Notes on Exercise 6

As you have likely noticed when experimenting with `WhatCounts` the runtime type of a polymorphic reference determines which implementation of an object method is used. Thus, even though `beta` is declared as a `BasicCounter`, when its `increment` method is called, the value is "doubly" incremented because the runtime type of the object it refers to is `DoubleCounter`. This is referred to as dynamic dispatch, and it is covered in more detail in Weiss 4.9.

In contrast, when methods are overloaded (as opposed to overridden), finding the appropriate method via signature matching strictly uses the static type of the variables in question.