Chapter 8: Understanding Inheritance

Download Report

Transcript Chapter 8: Understanding Inheritance

Session 16
Chapter 8: Understanding Inheritance
ProjectileWorld is an Abstract Class
•
•
You cannot make objects of abstract classes directly, instead you inherit them.
Subclasses must override abstract methods
abstract public class ProjectileWorld extends Frame {
private int
angle;
private String message;
private Projectile projectile;
private Scrollbar slider;
...
/* -------------- inner classes -------------- */
private class FireButtonListener implements ActionListener {
public void actionPerformed( ActionEvent e ) {
projectile = makeProjectile( angle );
repaint();
}
} // end class FireButtonListen
/* -------------- abstract methods -------------- */
abstract protected Projectile makeProjectile( int startAngle );
} // end class ProjectileWorld
RevisedCannonWorld extends ProjectileWorld
public class RevisedCannonWorld extends ProjectileWorld
{
public RevisedCannonWorld()
{
super();
setTitle( "Like the Original CannonWorld" );
}
protected
{
double
double
double
Projectile makeProjectile( int startAngle )
radianAngle = startAngle * Math.PI / 180.0;
sinAngle
= Math.sin( radianAngle );
cosAngle
= Math.cos( radianAngle );
return new CannonBall (20 + (int) (30 * cosAngle),
dy(5+(int) (30 * sinAngle)),
5, 12 * cosAngle, -12 * sinAngle );
}
}
Use RevisedCannonWorld Normally
public class RevisedCannonWorldDriver {
public static void main( String[] args ) {
RevisedCannonWorld world = new RevisedCannonWorld();
world.show();
} // end main
} // end class RevisedCannonWorld
The Result:
A ProjectileWorld Framework
• 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.
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.
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.
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.
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!)
Using Images in Java
• Image class in java.awt.Image
• Toolkit (see section 17.6 of text) contains some
useful utilities:
– getImage() takes a string or URL and returns a value of
type Image
– getScreenSize() returns a Dimension object containing
the number of pixels of both the height and width
– getScreenResolution() returns the number of dots per
inch
• Dividing one by the other will yield the physical size of the screen
– getFontList() returns an array of strings that contain the
names of the fonts available on the current system
– etc....
Simple Image Code
import java.awt.*;
public class ImageTestApp extends Frame {
private Image demo;
public static void main(String[] args) {
ImageTestApp app = new ImageTestApp();
}
public ImageTestApp() {
setTitle( "Image Test" );
setSize( 450, 450 );
demo = Toolkit.getDefaultToolkit().getImage("logo.gif" );
show();
}
public void paint( Graphics g ) {
g.drawImage( demo, 200, 200, 50, 50, this );
}
} // end class ImageTestApp
Exercise with Image Code
• Modify the ImageTestApp so the logo
moves to where the mouse is pressed in
the frame.
A Solution
import java.awt.*;
import java.awt.event.*;
public class ImageTestApp extends Frame {
private Image demo;
private int demoX;
private int demoY;
private int demoSize;
public static void main(String[] args) {
ImageTestApp app = new ImageTestApp();
}
public ImageTestApp() {
setTitle( "Image Test" );
setSize( 450, 450 );
demo = Toolkit.getDefaultToolkit().getImage( "logo.gif" );
demoX = 200;
demoY = 200;
demoSize = 50;
addMouseListener( new MouseKeeper() );
show();
}
...
A Solution
import java.awt.*;
import java.awt.event.*;
public class ImageTestApp extends Frame {
...
public void paint( Graphics g ) {
g.drawImage( demo, demoX-demoSize/2, demoY-demoSize/2,
demoSize, demoSize, this );
}
private class MouseKeeper extends MouseAdapter {
public void mousePressed( MouseEvent e ) {
demoX = e.getX();
demoY = e.getY();
repaint();
} // end mousePressed
} // end private class MouseKeeper
} // end class ImageTestApp