09week8

advertisement
Java Interface, Abstract Class,
and Event-Driven Animations
Week 8
IAT-265, Fall 2009
Instructor: Eric Yang
SIAT SFU Surrey
1
About Midterm & Final Exam

Reduce the Midterm from 15% to 10% of your
final grade


Add an assignment to account for 5% of your
final grade


May use your final exam to override it if it turns out
to make you better off
Must be done individually and students will be
asked how & why each question is done in person
Final exam, as specified in Syllabus, must be
attained an passing grade (50%) in order to
obtain a clear pass (C- or better) - strictly
enforced!!
2
Today’s topics






The concept of Interface in Java
Implementing an Interface
Benefits of Interfaces
Abstract Class
Comparison of Interfaces and Abstract
Classes
Timer-Based Animation
3
The concept
of Interface in Java


A group of declared methods with no method bodies
(i.e. { … }) associated with them, and classes can
promise to implement it
Example:
public interface Mover {
boolean changeGear(int newValue);
void speedUp(int increment);
void applyBrakes(int decrement);
void move();
}
class MountainBike extends Bicycle implements Mover {
// You must implement here ALL the methods defined in Mover
}

The methods of an interface are also called abstract methods
because it only declares signatures without implementations
4
Why Interface?



Classes let us group similar objects together
Inheritance lets us group similar classes
together  major goal is code reuse
Sometimes we’d like to group together
objects that are related only because they all
share some common behaviours


E.g. think about humans, birds, ants, space aliens,
and robotics, what are the common behaviour
among them?
Is it appropriate to give them a single superclass?
5
Interface: Group Objects with the
Same Behaviours


Java’s interface specifies a set of responsibilities (in
other words – a role)
If a class promise to implement an interface, it must
implement every method declared in the interface



The interface provides an description of the capabilities it has
There is no code sharing involved with interface, as each class
has to implement its own version of the methods declared
A class can implement many interfaces, separated by
commas – a way to break single-parent inheritance
mode and build multiple is-a relationships:
TalentedPerson extends Person implements Walker, Pilot,
Friend, Musician {
…
}
6
Case study: An Interface for
Shape Classes

Creating classes to represent rectangles,
circles, and triangles and compute their area
and a perimeter
It may seem as though there
is an inheritance relationship
here, because rectangle,
circle, and triangle are all
shapes

But code sharing isn’t useful
in this case because each
shape computes its area and
perimeter in a totally different
way

7
Define Interface Shape

A better solution would be to write an interface called
Shape to represent the common functionality of all
shapes: the ability to compute an area and a
perimeter
// A general interface for all shape classes
public interface Shape {
public double getArea();
public double getPerimeter();
}
An interface cannot be instantiated. In our case, any code trying to
create a new Shape() would not compile
It is, however, legal to create variables of type Shape that can refer to
any object that implements the Shape interface
8

Implementing an Interface

We must do two things:



Declare that a class “implments” the interface
Implement each of the interface’s methods in the
class
The general syntax for declaring that a class
implements interfaces is the following:
public class <name> implements <interface name>,
<interface name>, …, <interface name> {
. . .
}
9
class Rectangle implements
interface Shape
public class Rectangle implements Shape {
private double width;
private double height;
// Constructs a new rectangle with the given dimensions.
public Rectangle(double width, double height) {
this.width = width;
this.height = height;
}
// Returns the area of this rectangle.
public double getArea() {
return width * height;
}
// Returns the perimeter of this rectangle.
public double getPerimeter() {
return 2.0 * (width + height);
}
}
10
class Circle implements interface
Shape
public class Circle implements Shape {
private double radius;
// Constructs a new circle with the given radius.
public Circle(double radius) {
this.radius = radius;
}
// Returns the area of this circle.
public double getArea() {
return Math.PI * radius * radius;
}
// Returns the perimeter of this circle.
public double getPerimeter() {
return 2.0 * Math.PI * radius;
}
}
11
class Triangle implements
interface Shape
public class Triangle implements Shape {
private double a;
private double b;
private double c;
// Constructs a new Triangle given side lengths.
public Triangle(double a, double b, double c) {
this.a = a;
this.b = b;
this.c = c;
}
As per Heron’s formula, the
area of a triangle with sides of
length a, b, and c is related to
a value s equal to half the
triangle’s perimeter:
// Returns this triangle's area using Heron's formula.
public double getArea() {
double s = (a + b + c) / 2.0;
return Math.sqrt(s * (s - a) * (s - b) * (s - c));
}
// Returns the perimeter of this triangle.
public double getPerimeter() {
return a + b + c;
}
}
12
Benefits of Interfaces

Classes that implements a common
interface form a type hierarchy similar to
those created by inheritance


The interface serves as a parent type for
the classes that implement it
The major benefit of interfaces is that
we can use them to achieve polymorphism
13
Polymorphism – Its 2nd Meaning

Parent class or interface can be used as the declared
type of its subclasses

E.g. if we have an interface Mover (with a method move()
declared) that is implemented by classes AirPlane, Whale, and
Bicycle, we can then write:
Mover mover = new AirPlane();
or
Mover mover = new Whale ();
or
Mover mover = new Bicycle ();



If we send the message
mover.move();

The variable will move according to its actual type: AirPlane: fly in
the sky, Whale: swim, and Bicycle: roll
14
Polymorphism in Action

Allow us to do unified processing to objects of different types:
 Create an array of Shape and then process using loops
 Define a Shape as parameter to a method
 Return a Shape from a method
public class ShapesMain {
public static void main(String[] args) {
Shape[] shapes = new Shape[3];
shapes[0] = new Rectangle(18, 18);
shapes[1] = new Triangle(30, 30, 30);
shapes[2] = new Circle(12);
for (int i = 0; i < shapes.length; i++) {
System.out.println("area=" + shapes[i].getArea() +
", perimeter=" + shapes[i].getPerimeter());
}
}
}
15
Abstract Class




First let’s look at an example, and then we talk about why we
need a class type – Abstract Class in Java
Think about a class for all Animals, we can define a standard
move method for them:
public abstract class Animal {
…
public void move (Location location){
legs.moveForward();
…
}
}
However, different animal types move in very different ways:
Monkeys, Swans, Snakes, Penguins, … 
Makes a single standard implementation for all impossible
16
Why Abstract Class?

When you want all the subclasses of a
given class to define the same method,
but there is no standard implementation,
the solution is to define an abstract
class that incorporates an abstract
method
17
Syntax for Abstract Class

In Java, a class that contains an abstract method must
itself be declared as an abstract class, like this:
public abstract class Animal {
…
public abstract void move (Location
location);
}

An abstract method is one declared without an
implementation (i.e. no method body { … })

Different from interface, abstract class’ abstract methods must
use the abstract keyword
18
Annotations for Abstract Class

An abstract class is one declared abstract:



An abstract class doesn’t have to contain any
abstract method
When a class contains an abstract method, it
must be declared as abstract
Abstract class cannot be instantiated, but can
be used as superclass

Like interface, it can serve as declared type for its
subclasses’ objects  to realize polymorphism
19
Object
AWT
Abstract Classes in
AWT & Swing
Component
Container
Window
Frame
JFrame
Class
Layout manager
classes are in
the AWT
Abstract Class
Swing
JComponent
AbstractButton
JPanel
JLabel
JMenuBar
JTextComponent
JMenuItem
JButton
JMenu
JTextArea
JTextField
20
Comparison of Interfaces and
Abstract Classes
21
Timer-Based Animation

The basic idea behind animation:

Draw a graphical image over and over with
slight changes from time to the next, so
that it looks as though:



Moving
Changing size, angle, color, etc.
To make this work, Java provides a
Timer object

javax.swing.Timer
22
How Java Timer works

javax.swing.Timer works like a metronome:




Once we start it, it keeps on going until we stop it
While going, it provides a steady “ticking” that only
the program can hear
On each tick, certain actions that we can specify
are performed
To understand how this work, you need to
know Java Event Model
23
The Java Event Model

Some source objects (timer, button, window,
mouse, etc.) fire Events




Events: timer ticks; user presses a button or
selects a menu item, opens a window, clicks a
mouse, …
Any object interested in hearing about a
particular event can register with the event
source as a listener
When the event happens, Java notifies the
listeners automatically
Each listener decides how it will respond with
its event handler method(s)
24
The Java Event Model (2)
25
Event-Handling Code
1.
2.
3.
Create a source (some object that
generates an event, like a Timer or its
subclass)
Create a middleman object called a
listener that registers with the source
Create one or more responders objects that will respond to the event
26
Example: 1. Define an Event
Source: MoveTimer
/**
* MoveTimer.java
* A subclass of javax.swing.Timer that can be used for animation.
* It also serves as an example of the code for an "event source" object.
*/
public class MoveTimer extends Timer {
private Mover _mover; // peer object
public MoveTimer (int anInterval, Mover aMover) {
super(anInterval, null);
•Mover – an interface - is
_mover = aMover;
this.addActionListener(new MoveListener(_mover));
the object that responds to
}
MoveTimer
}
•Any instance of a class
that implements the Mover
can play this role
27
Annotations for MoveTimer

Signature of Timer Constructor:
Timer(int delay, ActionListener listener)
 Parameters:


delay – time interval between ticks (in
milliseconds, 1 sec = 1000 milliseconds)
listener - an initial listener; can be null
28
2. Create a listener that registers
with the source
this.addActionListener(new MoveListener(_mover));
 This statement create a MoveListener object, and pass Mover
object to it, and register it as ActionListener with MoveTimer

public class MoveListener implements java.awt.event.ActionListener {
private Mover _mover;
public MoveListener (Mover aMover) {
super();
_mover = aMover;
}
public void actionPerformed(java.awt.event.ActionEvent e){
_mover.move();
}
}
29
Annotations for ActionListener

Defined in java.awt.event
package
public interface ActionListener extends EventListener{
actionPerformed(ActionEvent e);
}

The only thing the ActionListener interface
requires is an actionPerformed method


actionPerformed method is executed on each beat of
the MoveTimer
All it does here is to forward a message to the
responder: _mover.move();
30
3. Create responders - objects
that will respond to the event

These objects must know how to move, i.e.
with a move method implemented


A bouncing ball, a swimming fish, a moving
ladybug
We enforce this feature by defining an
interface – Mover, and requires these objects
implement it
/* Mover.java
* Interface for objects that can move to a specified location.
* Must be implemented by objects that respond to a MoveTimer.
*/
public interface Mover {
public void move();
}
31
Using MoveTimer for animation:
Make a Ball Bounce - BallApp
**
* BallApp.java
* Displays a window with a red circle on a white background.
*/
public class BallApp extends javax.swing.JFrame {
public BallApp (String title) {
super(title);
this.setSize(600, 450);
this.setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE);
this.add(new BallPanel());
this.setVisible(true);
}
public static void main (String [ ] args) {
BallApp app = new BallApp ("BallApp");
}
}
32
Using MoveTimer for animation:
Make a Ball Bounce - BallPanel
/* BallPanel.java
* Creates the panel to be placed inside the BallApp window.
*/
public class BallPanel extends javax.swing.JPanel implements Mover {
private final int INIT_X = 75; // attributes
private final int INIT_Y = 75;
private final int DIAMETER = 60;
private final int INTERVAL = 100;
private BouncingBall _ball; // components
private MoveTimer _timer;
public BallPanel () {
super();
_ball = new BouncingBall (java.awt.Color.red, this);
_timer = new MoveTimer(INTERVAL, this);
this.setBackground(java.awt.Color.white);
_ball.setLocation(INIT_X, INIT_Y);
_ball.setSize(DIAMETER, DIAMETER);
_timer.start();
}
33
Using MoveTimer for animation:
Make a Ball Bounce – BallPanel (2)
public void move() {
_ball.move();
this.repaint();
}
public void paintComponent (java.awt.Graphics aBrush) {
super.paintComponent(aBrush);
java.awt.Graphics2D betterBrush = (java.awt.Graphics2D) aBrush;
_ball.fill(betterBrush);
}
}

The BallPanel class contains a MoveTimer. When instantiate
MoveTimer we need to make two decisions:


How often it ticks (100 milliseconds in this case, framerate =
1000/100=10 fps)
what resopnder object should be register with it (better use BallPanel to
coordinate potential more than one animated object
34
Using MoveTimer for animation:
Make a Ball Bounce – BouncingBall
/**
* BouncingBall.java
* Extends ActiveEllipse, adding the ability to "bounce."
*/
public class BouncingBall extends ActiveEllipse implements Mover {
private int _changeX, _changeY; // attributes
private final int MOVE_LEN = 5;
private javax.swing.JPanel _panel; // peer object (and container)
private javax.swing.Timer _timer;
public BouncingBall (java.awt.Color aColor, javax.swing.JPanel aPanel){
super(aColor);
_changeX = MOVE_LEN;
_changeY = MOVE_LEN;
_panel = aPanel;
}
//Methods so the BouncingBall knows how to move
35
Using MoveTimer:
Make a Ball Bounce – BouncingBall (2)
public void move() {
int nextX = (int)this.getX() + _changeX;
int nextY = (int)this.getY() + _changeY;
this.setLocation(nextX, nextY);
}


If we don’t consider the bouncing on boundary
situation, just make the ball move, the
implementation above is good enough
So for each ball’s move:



we get the ball’s current position along x by calling
this.getX() and add the displacement _changeX;
we get the ball’s current position along y by calling
this.getY() and add the displacement _changeY;
Reset its location using the new position value:
this.setLocation(nextX, nextY);
36
As it is a bouncing ball …

We must consider the ball’s bouncing on the
bounds of the window
x
•When ball
hits panel’s
Min Bound X
 reverse
•When ball
hits panel’s
Min Bound Y
 reverse
•When ball
hits panel’s
Max Bound X
 reverse
•When ball
hits panel’s
Max Bound Y
 reverse
y
37
BouncingBall (2) – Adding Conditional
Check for Panel’s Bounds
public void move() {
int nextX = (int)this.getX() + _changeX;
int nextY = (int)this.getY() + _changeY;
if (nextX <= this.getMinBoundX()) {
_changeX *= -1;
nextX = this.getMinBoundX();
}
else if (nextX >= this.getMaxBoundX()) {
_changeX *= -1;
nextX = this.getMaxBoundX();
}
if (nextY <= this.getMinBoundY()) {
_changeY *= -1;
nextY = this.getMinBoundY();
}
else if (nextY > this.getMaxBoundY()){
_changeY *= -1;
nextY = this.getMaxBoundY();
}
this.setLocation(nextX, nextY);
}
38
Calculate the Ball’s Bounds …

As (nextX, nextY) are about the upper-left corner’s
coordinates, so we must calcuate Ball’s bounds
relative to it
x
•MinBoundX =
panel’s x
•MinBoundY =
panel’s y
• MaxBoundX
= panel’s x +
panel width –
ball’s width
•MaxBoundY =
panel’s y +
panel height –
ball’s height
y
39
BouncingBall (3) – Adding get methods for
Min- & Max Bounds
public int getMinBoundX() {
return (int) _panel.getX();
}
public int getMinBoundY() {
return (int) _panel.getY();
}
public int getMaxBoundX() {
return (int) (_panel.getX() + _panel.getWidth()
- this.getWidth());
}
public int getMaxBoundY() {
return (int) (_panel.getY() + _panel.getHeight()
- this.getHeight());
}
}
40
Download