Lab: Questions About Abstract Classes and Interfaces
Instructions:
Answer as many of the following questions as you can during the lab period.
If you are unable to complete the assignment during the lab period it
is strongly recommended that you complete it on your own.
Getting Ready:
Before going any further, you should:
-
Make a directory for this lab.
-
Setup your development environment.
-
Download the following files:
to the appropriate directory/directories. (In most browsers, the
easiest way to do this is by right-clicking on each of the links
above.)
For a variety of reasons (that you will understand later in the semester),
you will get a warning when you compile some of the classes that
says something like:
... uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
You can and should just ignore this warning.
1. Basics:
This part of the lab will help you determine whether you understand
some of the basic issues involving abstract classes and interfaces.
-
Familiarize yourself with the
Comparator
interface. (Note: For the time being, when you see a class with
a one-letter name like T
, you should assume that it is
the Object
class.)
-
What methods are required of classes that implement the
Comparator
interface?
public int compare(Object firstObject, Object secondObject)
public boolean equals(Object other)
-
The
DirectoryComparator
class will compile
without error even though it doesn't implement the
equals(Object)
method required by the
Comparator
interface. Why?
There are actually two reasons. First, it inherits the
method from the Object
class. However, even if it didn't,
it would compile because it is an abstract class and, as such, is not
required to implement all of its methods (even those it "promises" to
implement).
-
The
DirectoryComparator
class is abstract.
What does that mean?
You can't create instances of DirectoryComparator
(i.e., you can't create objects that are members of the
class DirectoryComparator
).
-
What method(s) in the
DirectoryComparator
class
must be implemented by concrete children?
The compare(File, File)
method must be implemented.
The equals(Object)
method needn't be implemented
because it is inherited from the Object
class.
-
DirectoryNameComparator
extends DirectoryComparator.
What method must it implement (in order to be concrete)?
The compare(File, File)
method (as discussed above).
-
Does the
DirectoryNameComparator
implement the Comparator
interface?
It does, but "indirectly" since it's parent implements
the interface.
-
In the
main()
method of the DirectorySorter
class, the variable comparatorToUse
is declared
to be a Comparator
. Why is it possible
to assign a DirectoryNameComparator
or
a DirectoryDateComparator
to
comparatorToUse
?
DirectoryNameComparator
and
DirectoryDateComparator
implements the
Comparator
interface. Hence, for all intents
and purposes, it behaves like it "is a" Comparator
.
-
When the
DirectorySorter
is executed with no command-line
arguments, the compare(Object, Object)
message
is sent to comparatorToUse
by Arrays.sort()
.
Trace the methods that are executed as a result of this message.
[Note: For each step, list the signature of the method
that is called and the class it is in.]
1. compare(Object, Object) in DirectoryComparator
2. compare(File, File) in DirectoryNameComparator
2. Design Issues:
This part of the lab will help you determine whether you understand
some of the issues involved in designing abstract classes and interfaces.
-
What useful behavior/functionality do concrete children inherit
from
DirectoryComparator
?
The compare(Object, Object)
method casts the
parameters as File
objects and calls the
compare(File, File)
method.
-
Why does it make sense to have an abstract
DirectoryComparator
class? In other words, why shouldn't we just include the
compare(Object, Object)
method in the
DirectoryDateComparator
class?
Because we might have other ways of comparing directories (e.g.,
based on size) that could use the
compare(Object, Object)
method in the
DirectoryComparator
class.
-
The
DirectorySorter
class contains a
containsSwitch
method. Why must this method
be static?
It is called from the main()
method which is static.
(Since main()
is static, it can be executed even if
a DirectorySorter
object does not exist. Hence,
all methods and attributes it uses must also be static.)
-
Draw a UML class diagram that shows the relationship between
java.lang.Comparator
,
DirectoryComparator
,
DirectoryDateComparator
,
DirectoryNameComparator
, and
java.lang.Object
.
(NOTE: You do not have to submit your answer to this question.)
3. More Design Issues:
This part of the lab will help you determine whether you understand
some of the issues involved in designing systems that have
abstract classes and interfaces.
-
Some of the classes and interfaces from previous labs are
summarized in the following UML class diagram:
Familiarize yourself with (or refresh your memory about) these
classes and interfaces. (Note: In UML, abstract methods/classes are
denoted by slanted text, specialization is denoted by an arrow with
a solid line, and realization/implementation of an interface is denoted
by an arrow with a dashed line.)
-
Why is it a good idea to include the
TwoPartNumber
class in this design? In other words, what would be bad about omitting
the abstract TwoPartNumber
class?
It implements methods that are needed in both of its subclasses,
Length
and Weight
.
If it were omitted, those two classes would contain duplicate code.
-
Concrete subclasses of
TwoPartNumber
must have an
initializeUnits()
method. What must be done in this method?
The units for the small and large components must be initialized and
smallsPerLarge
must be initialized.
-
Why is this abstract method included in
TwoPartNumber
(rather than, for example, simply including a comment that says
all subclasses must have such a method)?
There are two reasons. First, by including it as an abstract method the
compiler can check to ensure if the method has been included in concrete
subclasses. Second, the initializeUnits()
method is
called in the TwoPartNumber
class' constructor.
-
Syntactically, why must the
TwoPartNumber
class
be declared abstract?
Because it has an abstract method.
-
Conceptually, why should the
TwoPartNumber
class
be declared abstract?
It doesn't make sense to have TwoPartNumber
objects.
Length
and Weight
objects correspond to
real-world entities/concepts but TwoPartNumber
objects do not.
-
Why is it a good idea to include the
Comparable
interface in this design?
It allows us to identify which objects can be compared and,
hence, whether an array of a particular kind of objects
can be sorted.
-
In this design, how are
TwoPartNumber
and
HolidayAccount
related?
They are only related indirectly. That is, they are both
Comparable
.
-
Why doesn't it make sense to have
HolidayAccount
extend TwoPartNumber
?
Because there is no sense in which a
HolidayAccount
"is a" TwoPartNumber
.
They have no attributes in common and the only method they
have in common is compareTo()
(and, perhaps,
toString()
).