Session 15 Chapter 8: Understanding Inheritance. Lab Exercise Solution Recall that we needed to know...

52
Session 15 Chapter 8: Understanding Inheritance

Transcript of Session 15 Chapter 8: Understanding Inheritance. Lab Exercise Solution Recall that we needed to know...

Page 1: Session 15 Chapter 8: Understanding Inheritance. Lab Exercise Solution Recall that we needed to know if a mousePress occurred on a target. We tried to.

Session 15

Chapter 8: Understanding Inheritance

Page 2: Session 15 Chapter 8: Understanding Inheritance. Lab Exercise Solution Recall that we needed to know if a mousePress occurred on a target. We tried to.

Lab Exercise Solution• Recall that we needed to know if a mousePress

occurred on a target. We tried to leverage the intersects method of PinBallTarget interface by creating a temporary ball at the point of the mouse press:

Ball tempBall = new PinBall( e.getX(), e.getY() );

for ( int j = 0; j < targets.size(); j++ ) {

PinBallTarget target=(PinBallTarget) targets.elementAt(j);

if ( target.intersects( tempBall ) ) {

startPressed = 1;

element = target;

} // end if

} // end for

Page 3: Session 15 Chapter 8: Understanding Inheritance. Lab Exercise Solution Recall that we needed to know if a mousePress occurred on a target. We tried to.

Question

• If you had to pick one word that identifies the key concepts of this course so far, what would it be? Why?

Page 4: Session 15 Chapter 8: Understanding Inheritance. Lab Exercise Solution Recall that we needed to know if a mousePress occurred on a target. We tried to.

My Answer

• If you had to pick one word that identifies the key concepts of this course so far, what would it be? Why?

– I think I might pick “Inheritance”

Page 5: Session 15 Chapter 8: Understanding Inheritance. Lab Exercise Solution Recall that we needed to know if a mousePress occurred on a target. We tried to.

InheritanceWhat?

A mechanism for reusing code in an existing class.A mechanism for organizing kinds of objects that have

the same implementation.How?

Create a class that extends another class.Why?

Who wants to rewrite code??Reuse provides:

• reliability through continual testing• shorter development time• ability to build frameworks (don’t call us...)

You can quickly build an application for demonstration purposes.

Page 6: Session 15 Chapter 8: Understanding Inheritance. Lab Exercise Solution Recall that we needed to know if a mousePress occurred on a target. We tried to.

ExerciseOn Page 132, Budd describes how we might

implement the class Set as a subclass of class Vector. A Set lets you add an element to it only if the Set doesn’t already contain that element.

What messages should a set respond to?

Page 7: Session 15 Chapter 8: Understanding Inheritance. Lab Exercise Solution Recall that we needed to know if a mousePress occurred on a target. We tried to.

Another ExerciseOn Page 132, Budd describes how we might

implement the class Set as a subclass of class Vector. A Set lets you add an element to it only if the Set doesn’t already contain that element.– addElement( Object )– removeElement( Object )– contains( Object )– isEmpty()– size()

If ‘Set extends Vector’, which of these are already in existence? Which are correct?

http://java.sun.com/j2se/1.4.2/docs/api/java/util/Vector.html

Page 8: Session 15 Chapter 8: Understanding Inheritance. Lab Exercise Solution Recall that we needed to know if a mousePress occurred on a target. We tried to.

Another ExerciseOn Page 132, Budd describes how we might

implement the class Set as a subclass of class Vector. A Set lets you add an element to it only if the Set doesn’t already contain that element. – addElement( Object )– removeElement( Object )– contains( Object )– isEmpty()– size()

Write the addElement method that we need to complete the Set class.

Page 9: Session 15 Chapter 8: Understanding Inheritance. Lab Exercise Solution Recall that we needed to know if a mousePress occurred on a target. We tried to.

Another ExerciseOn Page 132, Budd describes how we might

implement the class Set as a subclass of class Vector. A Set lets you add an element to it only if the Set doesn’t already contain that element.– addElement( Object )– removeElement( Object )– contains( Object )– isEmpty()– size()

If ‘Set extends Vector’ What other problem(s) do we have?

Page 10: Session 15 Chapter 8: Understanding Inheritance. Lab Exercise Solution Recall that we needed to know if a mousePress occurred on a target. We tried to.

A possible solutionimport java.util.Vector;public class Set extends Vector {

public Set() {super();

}public void addElement( Object object ) {

if ( !contains( object ))super.addElement( object );

}public int indexOf( Object newElement ) {

System.out.println("Set.indexOf is not allowed." );return -1;

}public Object elementAt( int index ) {

return null;}

}

Page 11: Session 15 Chapter 8: Understanding Inheritance. Lab Exercise Solution Recall that we needed to know if a mousePress occurred on a target. We tried to.

InheritanceIn one sense, a subclass is an expansion of its

superclass.• a subclass can add instance variables and methods

In another sense, a subclass is a contraction of its superclass.• a subclass defines a subset of instances of its superclass

In Java, all classes are subclasses, whether we say so or not. By default, any class that does not have an extends clause extends the class Object.

Consider our Ball hierarchy: Ball, MovableBall, BoundedBall

Page 12: Session 15 Chapter 8: Understanding Inheritance. Lab Exercise Solution Recall that we needed to know if a mousePress occurred on a target. We tried to.

public class Ball {private Rectangle location;private Color color;public Ball( int x, int y, int r ) { ... }public void paint( Graphics g ) { ... }public void setColor( Color newColor ) { ... }protected Rectangle region() { ... }protected Color color() { ... }protected int radius() { ... }protected int x() { ... }protected int y() { ... }protected void moveTo( int x, int y ) { ... }

}public class MovableBall extends Ball {

private double dx;private double dy;public MovableBall( int x, int y, int r ) { ... }public void move() { ... }public void setMotion( double ndx, double ndy ) { ... }protected double xMotion() { ... }protected double yMotion() { ... }

}public class BoundedBall extends MovableBall {

private Frame myWorld;public BoundedBall( int x, int y, int r, Frame myWorld ) { ... }public void move() { ... }

}

Page 13: Session 15 Chapter 8: Understanding Inheritance. Lab Exercise Solution Recall that we needed to know if a mousePress occurred on a target. We tried to.

Inheritance and Substitutability

An object X is substitutable for an object Y if• we can use X any place we use Y and

• the client code not know the difference.

An example in practice, from the pinball games:• The target vector holds any Object. That’s how Java

Vectors work.

• We put Springs, Walls, Holes, ..., into the vector.

• When we retrieve objects from the vector, we treat them as PinBallTargets.

Page 14: Session 15 Chapter 8: Understanding Inheritance. Lab Exercise Solution Recall that we needed to know if a mousePress occurred on a target. We tried to.

Inheritance and Substitutability

Another example in practice, from the cannon games:

• Our “fire” Button expects to be given an ActionListener that watches for button events.

• We create FireButtonListener as an implementation of the ActionListener interface.

• We add a FireButtonListener in place of an ActionListener.

What would the alternative be?

Page 15: Session 15 Chapter 8: Understanding Inheritance. Lab Exercise Solution Recall that we needed to know if a mousePress occurred on a target. We tried to.

Substitutability

The common feature in these cases — and the key to substitutability — is that the objects share a common interface.

They respond to the same messages.

Inheritance and interfaces are mechanisms for ensuring the common interface.

Page 16: Session 15 Chapter 8: Understanding Inheritance. Lab Exercise Solution Recall that we needed to know if a mousePress occurred on a target. We tried to.

Substitutability

So, why write our programs so that they use substitutable objects?• extendibility• flexibility• frameworks that implement a program’s control while

allowing programmers to add new objects to the program later

Of course, we can achieve these benefits without the use of inheritance and interfaces. But the compiler wouldn’t be able to help us enforce them!

Page 17: Session 15 Chapter 8: Understanding Inheritance. Lab Exercise Solution Recall that we needed to know if a mousePress occurred on a target. We tried to.

Types of Inheritance

• Specialization

• Specification

• Extension

• Combination

• Limitation

• Construction

Page 18: Session 15 Chapter 8: Understanding Inheritance. Lab Exercise Solution Recall that we needed to know if a mousePress occurred on a target. We tried to.

Types of Inheritance

Specialization• Essentially no new methods in the subclass.• Most subclass methods override inherited

methods.

• example: our BoundedBall class

• common in frameworks

Page 19: Session 15 Chapter 8: Understanding Inheritance. Lab Exercise Solution Recall that we needed to know if a mousePress occurred on a target. We tried to.

Types 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 ) { ... }

}

Page 20: Session 15 Chapter 8: Understanding Inheritance. Lab Exercise Solution Recall that we needed to know if a mousePress occurred on a target. We tried to.

Number - Abstract Class Example• Parent class for numeric wrapper classes:

Integer, Long, Double, etc.

• Subclasses must override abstract methods

public abstract class Number {

public abstract int intValue();

public abstract long longValue();

public abstract float floatValue();

public abstract double doubleValue()

public byte byteValue() {return (byte) intValue;}

public short shortValue() {

return (short) intValue();

}

} // end Number

Page 21: Session 15 Chapter 8: Understanding Inheritance. Lab Exercise Solution Recall that we needed to know if a mousePress occurred on a target. We tried to.

Types of Inheritance

Extension• Subclass uses most or all inherited methods

as-is.

• Subclass adds new behavior and methods.

• example: our MovableBall class

Page 22: Session 15 Chapter 8: Understanding Inheritance. Lab Exercise Solution Recall that we needed to know if a mousePress occurred on a target. We tried to.

Types of InheritanceCombination

• A class inherits from two or more classes. This is called multiple inheritance.

• Some OOP languages provide it (C++). Some don’t (Java, Smalltalk).• Java does support combination through interfaces.

• example: Budd’s Hole class

class Hole extends Ball implements PinBallTarget {public Hole( int x, int y ) { ... }public boolean intersects( Ball aBall ) { ... }public void hitBy ( Ball aBall ) { ... }

}

Page 23: Session 15 Chapter 8: Understanding Inheritance. Lab Exercise Solution Recall that we needed to know if a mousePress occurred on a target. We tried to.

Other 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.

Page 24: Session 15 Chapter 8: Understanding Inheritance. Lab Exercise Solution Recall that we needed to know if a mousePress occurred on a target. We tried to.

Other 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: Java’s Stack class (ouch!)• Construction may violate the principle of

substitutability.

JUST DON’T DO IT.

Page 25: Session 15 Chapter 8: Understanding Inheritance. Lab Exercise Solution Recall that we needed to know if a mousePress occurred on a target. We tried to.

An Exercisepublic class Set extends Vector ...

If limitation and construction are bad ideas, what should we do instead???

Implement your own Set class that avoids the improperuse of inheritance with limitation.Sets respond to these messages:• addElement( Object )• removeElement( Object )• contains( Object )• isEmpty()• size()

Page 26: Session 15 Chapter 8: Understanding Inheritance. Lab Exercise Solution Recall that we needed to know if a mousePress occurred on a target. We tried to.

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.

Page 27: Session 15 Chapter 8: Understanding Inheritance. Lab Exercise Solution Recall that we needed to know if a mousePress occurred on a target. We tried to.

An 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 aren’t already in the set.

Page 28: Session 15 Chapter 8: Understanding Inheritance. Lab Exercise Solution Recall that we needed to know if a mousePress occurred on a target. We tried to.

Possible Solution for Set Classimport java.util.Vector;

public class Set {private Vector myStuff;

public Set() {myStuff = new Vector();

}

// Methods provided in a bit}

Page 29: Session 15 Chapter 8: Understanding Inheritance. Lab Exercise Solution Recall that we needed to know if a mousePress occurred on a target. We tried to.

Possible Methods for Set Classpublic 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();}

Page 30: Session 15 Chapter 8: Understanding Inheritance. Lab Exercise Solution Recall that we needed to know if a mousePress occurred on a target. We tried to.

A driver classimport Set;public class SetDemo {

public static void main( String[] args ) {Set arguments = new Set();

for (int i = 0; i < args.length; i++)arguments.addElement( args[i] );

System.out.println( "Is the set empty? " + arguments.isEmpty() );

System.out.println( "Number of unique arguments: " +arguments.size() );

}}

Page 31: Session 15 Chapter 8: Understanding Inheritance. Lab Exercise Solution Recall that we needed to know if a mousePress occurred on a target. We tried to.

Sample output

$ javac SetDemo.java

$ java SetDemoIs the set empty? trueNumber of unique arguments: 0

$ java SetDemo a b a b a b a b a bIs the set empty? falseNumber of unique arguments: 2

Page 32: Session 15 Chapter 8: Understanding Inheritance. Lab Exercise Solution Recall that we needed to know if a mousePress occurred on a target. We tried to.

Reconsidering the Design of CannonWorld

• Why limit our shelves to shooting cannon balls?!!!

Page 33: Session 15 Chapter 8: Understanding Inheritance. Lab Exercise Solution Recall that we needed to know if a mousePress occurred on a target. We tried to.

Reconsidering 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

Page 34: Session 15 Chapter 8: Understanding Inheritance. Lab Exercise Solution Recall that we needed to know if a mousePress occurred on a target. We tried to.

Currently, 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( ... ) { ...cannonBall = new CannonBall (...);

...}}

...}

Page 35: Session 15 Chapter 8: Understanding Inheritance. Lab Exercise Solution Recall that we needed to know if a mousePress occurred on a target. We tried to.

The 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.

Page 36: Session 15 Chapter 8: Understanding Inheritance. Lab Exercise Solution Recall that we needed to know if a mousePress occurred on a target. We tried to.

The 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 shouldn’t 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!

Page 37: Session 15 Chapter 8: Understanding Inheritance. Lab Exercise Solution Recall that we needed to know if a mousePress occurred on a target. We tried to.

Reconsidering the Design of CannonWorld

Notice that the CannonWorld doesn’t 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.

Page 38: Session 15 Chapter 8: Understanding Inheritance. Lab Exercise Solution Recall that we needed to know if a mousePress occurred on a target. We tried to.

Step 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.

Page 39: Session 15 Chapter 8: Understanding Inheritance. Lab Exercise Solution Recall that we needed to know if a mousePress occurred on a target. We tried to.

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)

Page 40: Session 15 Chapter 8: Understanding Inheritance. Lab Exercise Solution Recall that we needed to know if a mousePress occurred on a target. We tried to.

Step 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 object’s instance variables should be its own instance methods.

Page 41: Session 15 Chapter 8: Understanding Inheritance. Lab Exercise Solution Recall that we needed to know if a mousePress occurred on a target. We tried to.

Step 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 let’s refactor the CannonBall class so that it also implements the Projectile interface:

(CannonBall.java)

Page 42: Session 15 Chapter 8: Understanding Inheritance. Lab Exercise Solution Recall that we needed to know if a mousePress occurred on a target. We tried to.

Step 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.

Page 43: Session 15 Chapter 8: Understanding Inheritance. Lab Exercise Solution Recall that we needed to know if a mousePress occurred on a target. We tried to.

Step 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.

Page 44: Session 15 Chapter 8: Understanding Inheritance. Lab Exercise Solution Recall that we needed to know if a mousePress occurred on a target. We tried to.

Step 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.

Page 45: Session 15 Chapter 8: Understanding Inheritance. Lab Exercise Solution Recall that we needed to know if a mousePress occurred on a target. We tried to.

Step 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 CannonBall’s 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)

Page 46: Session 15 Chapter 8: Understanding Inheritance. Lab Exercise Solution Recall that we needed to know if a mousePress occurred on a target. We tried to.

We have just converted our CannonWorld program intoa framework

Page 47: Session 15 Chapter 8: Understanding Inheritance. Lab Exercise Solution Recall that we needed to know if a mousePress occurred on a target. We tried to.

The Result:A 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.

Page 48: Session 15 Chapter 8: Understanding Inheritance. Lab Exercise Solution Recall that we needed to know if a mousePress occurred on a target. We tried to.

Using 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.

Page 49: Session 15 Chapter 8: Understanding Inheritance. Lab Exercise Solution Recall that we needed to know if a mousePress occurred on a target. We tried to.

Step 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)

Page 50: Session 15 Chapter 8: Understanding Inheritance. Lab Exercise Solution Recall that we needed to know if a mousePress occurred on a target. We tried to.

The 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 program’s behavior from the classes in the framework.

Page 51: Session 15 Chapter 8: Understanding Inheritance. Lab Exercise Solution Recall that we needed to know if a mousePress occurred on a target. We tried to.

The 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 “don’t call us; we’ll call you” mentality.

Page 52: Session 15 Chapter 8: Understanding Inheritance. Lab Exercise Solution Recall that we needed to know if a mousePress occurred on a target. We tried to.

The 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 don’t want our abstract class to commit to a class for its instance vars!)