Title: Chapter 10
1Session 19
- Chapter 10 Mechanisms for Software Reuse
2Lab 6
- Available on the website
- This assignment asks you to design your own
object-oriented program and build it "from
scratch". - Your task is to write a program that simulates a
simple voice-mail system. - For now, we will use a text-based interface
3Types of Inheritance
- Specialization
- Specification
- Extension
- Combination
- Limitation
- Construction
4Types of Inheritance
- Specialization
- Essentially no new methods in the subclass.
- Most subclass methods override inherited
methods. - example our game worlds
- example our BoundedBall class
- common in frameworks
5Types of Inheritance
- Specification
- Superclass provides responsibility but no
behavior. - Implement an interface or extend an abstract
class. - example our event listeners, pinball targets
- private class MouseKeeper extends MouseAdapter
- private PinBallTarget element
- public void mousePressed ( MouseEvent e ) ...
- public void mouseReleased( MouseEvent e ) ...
-
6Types of Inheritance
- Extension
- Subclass uses most or all inherited methods
as-is. - Subclass adds new behavior and methods.
- example our MovableBall class
7Types of Inheritance
- Combination
- A class inherits from two or more classes. This
is called multiple inheritance. - Some OOP languages provide it (C). Some
dont (Java, Smalltalk). - Java does support combination through
interfaces. - example Budds Hole class
- class Hole extends Ball implements PinBallTarget
- public Hole( int x, int y ) ...
- public boolean intersects( Ball aBall ) ...
- public void hitBy ( Ball aBall ) ...
8Other Types of Inheritance
- Limitation
- The subclass primarily has methods that
override inherited methods. - to restrict a behavior (example Square extends
Rectangle) - to remove a behavior (example Set extends
Vector) - Limitation violates the principle of
substitutability. -
9Other Types of Inheritance
- Construction
- The subclass reuses a class because it provides
needed functionality... - ... but it is not necessarily true that an
instance of the subclass is an instance of the
superclass. - example Javas Stack class (ouch!)
- Construction may violate the principle of
substitutability. - JUST DONT DO IT.
10An Exercise
- public class Set extends Vector ...
- If limitation and construction are bad ideas,
what should we do instead??? - Implement your own Set class that avoids the
improper - use of inheritance with limitation.
- Sets respond to these messages
- addElement( Object )
- removeElement( Object )
- contains( Object )
- isEmpty()
- size()
11Remember this slide?Class Interaction
- Relationships between classes
- 1. composition
- A Ball contains a Color.
- An instance of Color is a part of a Ball.
- 2. inheritance
- A MovableBall is a kind of Ball.
- A CannonWorld is a kind of Frame.
- 3. association
- A BoundedBall interacts with the Frame that
contains it.
12An Exercise
- Inheritance is only one way to reuse a class.
Another is composition having an instance of the
class as an instance variable. - So, instead of extending Vector, a Set can have a
Vector instance variable, to which the set adds
only elements that arent already in the set.
13Possible Solution for Set Class
- import java.util.Vector
- public class Set
- private Vector myStuff
- public Set()
- myStuff new Vector()
-
- // Methods provided in a bit
14Possible Methods for Set Class
- public void addElement( Object newElement )
- if ( !( myStuff.contains( newElement ) ) )
- myStuff.addElement( newElement )
-
- public boolean removeElement( Object newElement )
- return myStuff.removeElement( newElement )
-
- public boolean contains( Object newElement )
- return myStuff.contains( newElement )
-
- public boolean isEmpty()
- return myStuff.isEmpty()
-
- public int size()
- return myStuff.size()
15A driver class
- import Set
- public class SetDemo
- public static void main( String args )
- Set arguments new Set()
- for (int i 0 i lt args.length i)
- arguments.addElement( argsi )
- System.out.println( "Is the set empty? "
arguments.isEmpty() ) - System.out.println( "Number of unique
arguments " arguments.size() ) -
16Sample output
- javac SetDemo.java
- java SetDemo
- Is the set empty? true
- Number of unique arguments 0
- java SetDemo a b a b a b a b a b
- Is the set empty? false
- Number of unique arguments 2
17Reconsidering the Design of CannonWorld
- Why limit our shelves to shooting cannon balls?!!!
18Reconsidering the Design of CannonWorld
- But does it have to shoot only cannon balls? Of
course not! All the CannonWorld needs is an
object that can... - move under its own control
- paint itself to the screen
- tell the CannonWorld where it lies relative to
the floor and the target
19Currently, CannonWorld is hardwired to a
CannonBall
- public class CannonWorld extends Frame ...
- private CannonBall cannonBall
- ...
- public CannonWorld() ...
- cannonBall null
- ...
- ...
- protected void drawCannonBall(Graphics g)
- if ( cannonBall ! null )
- ...
- cannonBall.move()
- cannonBall.paint( g )
- ... cannonBall.y() ...
- ... cannonBall.x() ...
- cannonBall null
- ...
- ...
- private class FireButtonListener ...
- public void actionPerformed( ... ) ...
20The Current State of Affairs
- The CannonWorld class is hardwired to the
CannonBall class in 3 ways - It sends messages that are defined in the
CannonBall class. - It declares an instance variable of type
CannonBall. - It calls new with a request for an instance of
class CannonBall.
21The Problem with the Current State of Affairs
- It sends messages that are defined in the
CannonBall class. - This limits CannonWorld to working with the
decisions made when implementing CannonBall. If
the CannonBall class was designed well, that
shouldnt be a problem. But... - It declares an instance variable of type
CannonBall. - This limits CannonWorld to working with an
instance of class CannonBall, or an instance of a
subclass of CannonBall. But... - It calls new with a request for an instance of
class CannonBall. - This limits CannonWorld to working only with
instances of class CannonBall no subclasses
allowed!
22Reconsidering the Design of CannonWorld
- Notice that the CannonWorld doesnt care...
- that its cannonball is affected by gravity...
If the object moves under its own control, then
gravity is a feature of the object flying through
the air! - what the x- and y-coordinates of its cannonball
are. It cares whether the ball has hit the floor
and the target. The messages sent by CannonWorld
to its cannonBall are an unfortunate remnant of
an implementation decision in the CannonBall
class. - Because this is true, we can generalize
CannonWorld so that it works with more than just
CannonBalls.
23Step 1 Make a Projectile Interface
- Write an interface named Projectile that
specifies objects which can... - move() according to a trajectory they know,
- paint() themselves to a Graphics context, and
- respond to boolean requests for their location
relative to a Point.
24- import java.awt.Graphics
- import java.awt.Point
- public interface Projectile
- public void move ()
- public void paint ( Graphics g )
- public boolean northOf( Point p )
- public boolean southOf( Point p )
- public boolean eastOf ( Point p )
- public boolean westOf ( Point p )
-
- (Projectile.java)
25Step 1 Make a Projectile Interface
- This interface defines the essential
responsibilities of the objects that a
CannonWorld shoots. - Notice that this interface requires the object to
respond to queries about its relative location,
rather than opening up its instance variables for
outside inspection. - The only methods to look at an objects instance
variables should be its own instance methods.
26Step 2 Make CannonBall Implement the Projectile
Interface
- We would like our CannonWorld to fire an instance
of any class that implements the Projectile
interface, but that mean that CannonBalls must be
Projectiles. So lets refactor the CannonBall
class so that it also implements the Projectile
interface - (CannonBall.java)
27Step 3 Make CannonWorld Fire Any Projectile
- If we write our CannonWorld program to use the
Projectile interface, then we are able to plug
in new projectiles relatively easily. - Programming to an abstract interface makes your
programs easier to reuse and less likely to
depend on implementation detail.
28Step 3 Make CannonWorld Fire Any Projectile
- In order for a CannonWorld to shoot Projectiles
like our new CannonBalls from its cannon, we need
to modify CannonWorld so that it uses a
Projectile instead of a CannonBall. So - Modify all references to the CannonBall in
CannonWorld to be references to a Projectile.
29Step 3 Make CannonWorld Fire Any Projectile
- This causes something of a problem, because we
cannot create an instance of an interface. So - Move the creation of the CannonBall into an
abstract protected helper method. The code that
creates the CannonBall should call this method
instead of calling new directly. This requires
that the class be abstract, too.
30Step 3 Make CannonWorld Fire Any Projectile
- These changes are actually pretty
straightforward... - Change the instance variable to be a Projectile.
- Leave all null assignments and move/paint
messages the same. - Change requests for the CannonBalls instance
variables (and the calculations on those values!)
into requests to a Projectile. - Replace the creation of the CannonBall with a
call to the abstract method that creates
instances. - (ProjectileWorld)
31We have just converted our CannonWorld program
into a framework
32The ResultA ProjectileWorld Framework
- ProjectileWorld is not just one program now. It
is either zero programs or as many programs as
you can imagine. - We can no longer run the ProjectileWorld program
by itself. In this way, it is not a program at
all. - But our new ProjectileWorld allows us to build a
working program that fires the projectile of our
choice in just two steps.
33Using the ProjectileWorld Framework
- To implement a working ProjectileWorld, a client
programmer need only - Write a class that implements the Projectile
interface. - Write a subclass of ProjectileWorld that
implements the makeProjectile(...) method to
create an instance of the new Projectile class.
34Step 4 Make a CannonWorld Class
- Hey! We already have the Projectile of our
choice the CannonBall. So we only have to do the
second step. - In order for a P r o j e c t i l e W o r l d to
shoot CannonBalls from its cannon, we need to
create a CannonWorld that uses a CannonBall
instead of a Projectile. So - (RevisedCannonWorld.java)
35The ProjectileWorld Framework
- We have built a ProjectileWorld framework two
classes that define an infinite number of
programs in terms of the abstract behaviors of
their collaborators. - The user of this framework is a programmer who
instantiates the abstract behaviors in concrete
classes. But these concrete classes inherit the
bulk of the programs behavior from the classes
in the framework.
36The ProjectileWorld Framework
- The ProjectileWorld framework is the same in
principle as the Java AWT. - The ProjectileWorld class is a lot like the
Frame class, which allows us to build functional
windows with relative ease. - The Projectile interface is a lot like the
listener interfaces that allow us to respond to
user events with relative ease. - The control of the application lies in
ProjectileWorld. The programmer uses the
framework classes with a dont call us well
call you mentality.
37The ProjectileWorld Framework
- The makeProjectile() method is a factory method.
It creates an object for the program, so that the
program does not have to use the new command
directly. (This is a common idea in frameworks,
because we dont want our abstract class to
commit to a class for its instance vars!)