| 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.
mkdir somewhere/inheritance
cd somewhere/inheritance
cp ~weinman/public_html/courses/CSC207/2011S/labs/code/inheritance/WhatCounts.java . cp ~weinman/public_html/courses/CSC207/2011S/labs/code/inheritance/WhatElseCounts.java .
Counter that
specifies capabilities of objects that count things, starting at some
value.
The interface should contain three public methods:
void increment(), which should indicate that it may
throw
an IllegalStateException;
void reset()
int value()
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:
int fields called count
and start. (These should be visible to derived
classes, but nothing else.)
count and
start to that value;
reset(), which resets count to
start;
value(), which returns the value of count
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.
BasicCounter that
extends AbstractCounter. It should have:
super to call the instructor of the
parent class.
increment() that adds 1
to count.
WhatCounts.java that you copied
in the lab preparations. What output do you expect?
WhatCounts.
alpha
in WhatCounts.java so that it reads:
Counter alpha = new AbstractCounter(0);
alpha to
a BasicCounter.
DecrementableCounter, that has
the following form:
/**
* 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
gamma
in WhatCounts.java so that it reads
Counter gamma = new DecrementableCounter(-5);
gamma so that it reads
DecrementableCounter gamma = new Counter(-5);
gamma to
Counter gamma = new DecrementableCounter(-5);
decrement() method
to DecrementableCounter This method should subtract
one from the count field.
WhatCounts to test that method.
LimitedCounter, that has the following form
/**
* 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
increment method so that it throws an
IllegalStateException when count
exceeds limit.
WhatCounts so that the initialization of
alpha reads
Counter alpha = new LimitedCounter(0);
alpha to
Counter alpha = new LimitedCounter(-5,3);
WhatCounts.
LimitedCounter and determine what errors, if any,
you get. Why do you think that is?
DoubleCounter, that has the
following form:
public class DoubleCounter
extends BasicCounter
{
} // class DoubleCounter
DoubleCounter of the
following form
public DoubleCounter(int start)
{
super(start);
} // DoubleCounter(int)
WhatCounts so that the initialization of
beta reads
Counter beta = new DoubleCounter(123);
increment method by inserting the
following code
into DoubleCounter
public void increment()
throws IllegalStateException
{
super.increment();
super.increment();
}
WhatCounts? Confirm or refute your prediction
experimentally.
LimitedCounter a subclass
of DoubleCounter rather than a subclass
of Counter. (That is, change the line that
reads extends Counter to read
extends DoubleCounter.)
WhatElseCounts.java that you copied
in the lab preparations. What output do you expect?
WhatElseCounts. Can you generalize the
pattern?
If you are having trouble, the notes on
this exercise gives some background.
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.
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.