public class

advertisement
Inheritance
Organizing Classes of Files
Promoting Reuse of Code
Polymorphism
The Purpose of Java Interfaces
An interface organizes java class files by using inheritance.
Any class that implements an interface must have all of the
methods that are listed in the interface. Those classes must
either provide code for each method or state that a subclass
will provide them.
The Java List Interface
Java provides the List interface and numerous classes
implement it. One class is the ArrayList class and another
is the LinkedList class.
If you use either the ArrayList or LinkedList classes in a
program, you call the same methods, like size(), add(obj),
add(i, obj), remove(i), set(i, obj), and get(i). But there is
different code for these methods in each one of the
classes.
In other words, the code for add(obj) in the ArrayList class is
different from the add(obj) code in the LinkedList class but
you call them the same way. These classes use different
approaches to implement these methods with the
LinkedList class striving to be more efficient by storing
data dynamically instead of statically. You won’t learn
about that in detail until Adv. Comp. Programming.
java.util.List
The List interface is part of the java.util package. So if you need
to declare an ArrayList variable of type List you do it as follows:
List <Student> shapes = new ArrayList <Student> ( );
and you need to import both of the following into your file:
import java.util.List;
import java.util.ArrayList;
There is an advantage of doing this in a program. If you
determined that it would be more efficient to use a LinkedList
instead of an ArrayList only one line of code in the program
needs to be changed … the original instantiation on the right
side where the list is declared …
List <Student> shapes = new LinkedList <Student> ( );
The java.util.List<E> interface
An interface tells you the method signatures of the methods
that classes that implement the interface must have.
Here is what part of Java’s List interface looks like:
public interface List
{
public int size ( );
public boolean add (E obj);
public void add (int index, E obj);
public E get (int index);
public E set (int index, E obj);
public E remove (int index);
…….
}
An interface has no
instance variables or
constructors and it
doesn’t have the code
for any method … just
the method
signatures! Notice the
method signatures
end in semicolons!
The Shape Program Series
You will be completing a series of programs that help you
learn inheritance:
Shape 1
Shape 2
Shape 3
Shape 4
ShapeMania
ShapeSorter
Before starting Shape1, let’s view the Shape interface and a
hierarchy of files we will be working with.
The Shape Interface
import java.awt.Color;
import java.awt.Graphics;
public interface Shape
{
public int getXPos();
public int getYPos();
public Color getColor();
public double area();
public void draw (Graphics g);
public void paint (Graphics g);
public void move (int xLoc, int yLoc);
public void stretchBy (int factor);
public String toString();
}
Here are the method
signatures of the
Shape inteface that
we will use.
Since Color is a return
value for the method
getColor() and g is a
parameter of two
methods, we must
import the respective
classes.
The Shape 1 Program Heirarchy
Shape Interface
Circle Class
Rectangle Class
Triangle Class
means implements
ShapePanel1
ShapeApplet1
means uses
ShapePanel uses the Shape Interface
because it declares variables of type Shape.
It also calls constructors and other methods of
the Circle, Rectangle, and Triangle classes.
Implementing an Interface
In the previous diagram, the Circle, Rectangle, and Triangle
classes implement the Shape interface, so their class
definition lines are as follows:
public class Circle implements Shape
public class Rectangle implements Shape
public class Triangle implements Shape
Constructing a List of Circle Objects
In a program file, we could construct numerous circles and place
them in an ArrayList using:
List <Circle> circles = new ArrayList <Circle> ( );
and
Circle c1 = new Circle (100, 100, 75, Color.blue);
circles.add(c1);
Circle c2 = new Circle (50, 50, 60, Color.yellow);
circles.add(c2);
……..
but if we constructed a rectangle and tried to add it with …
Rectangle r1 = new Rectangle (25, 25, 75, 50, Color.red);
circles.add(r1);
we would get a compile error. The same would happen if we
tried to add a Triangle. So we would be limited to placing only
circles in our ArrayList. So how do we add all shapes to a list?
Constructing a List of Shape Objects
We would declare and instantiate our ArrayList as follows:
List <Shape> shapes = new ArrayList <Shape> ( );
and
Shape s1 = new Circle (100, 100, 75, Color.blue);
shapes .add(s1);
Shape s2 = new Rectangle (25, 25, 75, 50, Color.red);
shapes .add(s2);
Shape s3 = new Triangle (0, 0, 50, 0, 25, 25, Color.red);
shapes .add(s3);
By placing all Shape objects in shapes, we can have shapes of
different types in one list!!!
Then we can use a loop to move them, draw them, or stretch all
of them. In fact this makes it easy to use enhanced for loops!
Traversing a List of Shape Objects
This enhanced for loop would draw all of the shapes:
for (Shape element: shapes)
{
element.draw(g);
}
or without an enhanced for loop, we could use:
for (int i = 0; i < shapes.size(); i++)
{
shapes.get(i).draw(g);
}
Using an Array of Shape Objects
It will be worthwhile to go over the last three slides using
standard arrays rather than an ArrayList beginning on the next
slide.
This will help familiarize you with the code for implementing a list
of Shape objects in different ways in the Shape Program
Series.
Constructing an Array of Circle Objects
Similarly if we were using a standard array created as follows:
Circle [ ] circles = new Circle [10];
and
Circle c1 = new Circle (100, 100, 75, Color.blue);
circles[0] = c1;
Circle c2 = new Circle (50, 50, 60, Color.yellow);
circles[1] = c2;
……..
but if we constructed a rectangle and tried to add it with …
Rectangle r1 = new Rectangle (25, 25, 75, 50, Color.red);
circles[2] = r1;
we would get a compile error. The same would happen if we
tried to add a Triangle. So we would be limited to placing only
circles in our array.
Constructing an Array of Shape Objects
We would declare and instantiate our array as follows:
Shape [ ] shapes = new Shape [10];
and
Shape s1 = new Circle (100, 100, 75, Color.blue);
shapes[0] = s1;
Shape s2 = new Rectangle (25, 25, 75, 50, Color.red);
shapes[1] = s2;
Shape s3 = new Triangle (0, 0, 50, 0, 25, 25, Color.red);
shapes[2] = s3;
Again, by placing all Shape objects in shapes, we can have
shapes of different types in one array!!!
Then we can use a loop to move them, draw them, or stretch all
of them. In fact this makes it easy to use an enhanced for loop!
Traversing a List of Shape Objects
This enhanced for loop would draw all of the shapes:
for (Shape element: shapes)
{
element.draw(g);
}
or without an enhanced for loop, we could use:
for (int i = 0; i < shapes.size(); i++)
{
shapes[ i ].draw(g);
}
Back to the Shape Hierarchy
Now that we have learned some basic information about
inheritance, let’s go back to the Shape 1 Hierarchy Diagram on
the next slide and explain why the arrows are shown as they
are.
The Shape 1 Program Heirarchy
Shape Interface
Circle Class
Rectangle Class
Triangle Class
means implements
ShapePanel1
ShapeApplet1
means uses
ShapePanel uses the Shape Interface
because it declares variables of type Shape.
It also calls constructors and other methods of
the Circle, Rectangle, and Triangle classes.
Explanation of Arrows
Obviously the dashed arrows mean implements. This means
that Circle, Rectangle, and Triangle implement a common set
of methods that have the same names and their classes must
provide the code for those methods.
It also means that a variable of type Shape can reference a
Circle object, Rectangle object, or Triangle object.
The normal arrows mean uses. This means that other files
outside of the hierarchy can use the interface or classes in
the hierarchy by declaring variables of any of those types,
constructing objects of those types, and most importantly
calling methods of those types.
In other words, an outside file can declare a variable of type
Shape, construct either a Circle, Rectangle, or Triangle for it
to refer to, and call any method in the interface.
Is-A and Has-A Relationships
Programmers like to be able to refer to the relationships of
classes or objects using two expressions:
•
is-A relationship
•
has-A relationship
You need to understand the basic meaning of these two
relationships for the AP Exam.
Examples follow on the next slides.
Is-A Relationships of Shape 1
Because of the class definition lines:
public class Circle implements Shape
public class Rectangle implements Shape
public class Triangle implements Shape
We can say that
a Circle “is a” Shape
a Rectangle “is a” Shape
a Triangle “is a” Shape
This is terminology that programmers use when discussing the
relationship between classes and interfaces within a hierarchy.
has-A Relationships of Shape 1
Also, we can express the relationship between classes that are
outside the hierarchy and those that are inside the hierarchy.
Since ShapePanel1 is outside the hierarchy, we can say that
ShapePanel1 “has a” Shape (three of them)
In fact, it has 3 shapes … a Circle, a Rectangle, and a Triangle,
because there are Shape variables s1, s2, and s3 that refer to
constructed Circle, Rectangle, and Triangle objects.
So we could also indirectly say that
ShapePanel1 “has a” Circle
ShapePanel1 “has a” Rectangle
ShapePanel1 “has a” Triangle
Coding the Shape 1 Program
So let’s get going … here is what has to be done:
• The coding of the Shape Interface file is done.
• Begin by coding the Circle class
• Next, code the Rectangle class
• Next, code the Triangle class
• Next, code the ShapePanel1 class
• The ShapeApplet1 driver class is done.
Sample output is available online.
The Shape 2 Program Heirarchy
Shape Interface
Circle Class
Rectangle Class
ConcentricCircle
Class
Triangle Class
means implements
means extends
means uses
ShapePanel2
ShapeApplet2
The Concentric Circle Shape
Notice a new kind of arrow in the Shape 2 Hierarchy Diagram …
a heavier solid arrow. The heavier solid arrow means
extends. It points from the ConcentricCircle class to the Circle
class. This indicates that the ConcentricCircle class inherits
all of the characteristics of the Circle class.
The class definition line for ConcentricCircle is:
public class ConcentricCircle extends Circle
The Concentric Circle Shape
More specifically, the heavier solid arrow means that …
• the ConcentricCircle class extends the Circle class.
• the ConcentricCircle class is a subclass of Circle.
• the Circle class is the superclass of ConcentricCircle.
• a ConcentricCircle object inherits all of the characteristics of a
Circle, plus has some additional ones it defines in its own
class.
You could think of a ConcentricCircle object as a child of the
parent class Circle, even though we won’t use child and
parent in referring to them.
Is-A Relationships of Shape 2
Because of the class definition lines:
public class Circle implements Shape
public class Rectangle implements Shape
public class Triangle implements Shape
public class ConcentricCircle extends Circle
Now we can say that …
a Circle “is a” Shape
a Rectangle “is a” Shape
a Triangle “is a” Shape
a ConcentricCircle “is a” Shape
a ConcentricCircle “is a” Circle
has-A Relationships of Shape 2
Now we can say that …
ShapePanel2 “has a” Shape (four of them)
In fact, it has 4 shapes … a Circle, a Rectangle, a Triangle, and
a ConcentricCircle because there are Shape variables s1, s2,
s3 and s4 that refer to constructed Circle, Rectangle, Triangle,
and ConcentricCircle objects.
So we could also indirectly say that
ShapePanel2 “has a” Circle
ShapePanel2 “has a” Rectangle
ShapePanel2 “has a” Triangle
ShapePanel2 “has a” ConcentricCircle
Protected vs. Private
For the ConcentricCircle class to function properly, it needs to
have access to its inherited characteristics (radius, xPos, yPos,
and color) that are defined in the Circle class.
This is possible by making the instance variables of Circle
protected rather than private. Making them protected allows a
subclass to have access to them but classes that are not
subclasses don’t have access. (By the way, don’t try to use
protected on the AP Exam. It is not part of the subset and you
will never be expected to use it.)
Note that ConcentricCircle itself has only one private instance
variable named numberOfCircles.
The Use of Super by Subclasses
Subclasses may call methods in their super class explicitly by
using the Java key word super.
You will notice that the first line of code in the ConcentricCircle
default constructor is: super( );
This code indicates that we are calling the default constructor in
the superclass Circle. This should be obvious since there are
empty parentheses following the word super.
After that code is executed, Java returns to ConcentricCircle
default constructor and executes the line of code:
numberOfCircles = 2;
The Use of Super by Subclasses
You will notice that the first line of code in the ConcentricCircle
initializing constructor is: super( xLoc, yLoc, r, c );
This code indicates that we are calling the initializing constructor
in the superclass Circle. This should be obvious since the
four parameters match what would be needed if someone was
calling the initializing constructor of the Circle class.
After that code is executed, Java returns to ConcentricCircle
initializing constructor and executes the line of code:
numberOfCircles = n;
// n is a parameter
In all cases of the use of super in a constructor method, it must
be used in the first line of code. This is a requirement of Java.
The Use of Super by Subclasses
You will notice that the first line of code in the ConcentricCircle
draw method is:
super.draw(g);
This code indicates that we are calling the draw method in the
superclass Circle to draw the outer most ring of the
ConcentricCircle object.
(If this line of code had not been first it would have been ok with
Java. We just decide to logically do it that way.)
After Java executes the code in Circle’s draw method, it returns
to the ConcentricCircle draw method and executes the
remainder of the code that draws the other concentric circles.
Overriding the Draw Method
By having a draw method in the ConcentricCircle class we are
overriding the draw method in the superclass Circle. Consider this:
• ConcentricCircle extends Circle so it inherits all of the characteristics
and methods of Circle. ConcentricCircle wouldn’t have to have a
draw method because it inherits it, but it needs a draw method so all
of the rings can be drawn. The work of drawing all of the rings can’t
be done in Circle’s draw method, because it can draw only one
circle.
• What is not evident is that if there was no draw method in
ConcentricCircle, then when draw is called for a ConcentricCircle
object, Java would automatically go up to the superclass Circle and
execute that method! So in this case overriding is a good thing and
prevents something from happening that we don’t want.
Not Overriding move() & stretchBy()
But is some cases not overriding is a good thing. We don’t
override move() and stretchBy() in ConcentricCircle because
we just want to use the code that is in those methods in Circle
when we want to move or stretch a ConcentricCircle.
So when you call move() or stretchBy() with a ConcentricCircle
object, Java doesn’t find those methods in ConcentricCircle so
it automatically goes up to the superclass Circle and if it finds
them then it executes them.
Note: overriding is not the same as overloading. See the Math
class PPT to review overloading.
Overridding the paint() method
We really can’t paint a ConcentricCircle object, because if we did
we wouldn’t be able to see the rings. It would be all one solid
color. So our first inclination might be to not provide a paint()
method in ConcentricCircle, but then we realize that a novice
programmer might try to call paint anyway and if they did then
it would execute the paint method in the Circle class and paint
the ConcentricCircle a solid color.
We prevent this from happening by overriding paint in
ConcentricCircle and then just calling draw inside of it. So if
someone calls paint for a ConcentricCircle object, Java finds
the paint method in ConcentricCircle which only does one
thing and that is call the draw method in ConcentricCircle.
This way we can be assured that a ConcentricCircle object is
always drawn and not painted.
The setNumberOfCircles() method
Besides moving or stretching a ConcentricCircle object, we may want to
change the number of concentric circles it has. To do this, we must call the
setNumberOfCircles() method. If we have used:
Shape s4 = new ConcentricCircle(……);
then because the setNumberOfCircles() method is not in the Shape interface,
but is a method specific to the ConcentricCircle class, we cannot call the
method as follows:
s4.setNumberOfCircles(10);
We must first explicitly cast s4 to a ConcentricCircle as follows:
((ConcentricCircle)s1).setNumberOfCircles(10);
Both sets of parentheses are necessary, because it is the casted object that
must make the call of the method.
The ClassCastException
If by accident, you miscode the method call by casting to the
wrong class as in …
((Circle)s1).setNumberOfCircles(10);
instead of
((ConcentricCircle)s1).setNumberOfCircles(10);
then you will get a ClassCastException, meaning that you are
trying to cast an object to a different type other than what it is.
You need to know what a ClassCastException is for the AP
Exam.
Coding the Shape 2 Program
Now its time to code the Shape 2 Program. Here is what to do:
• Modify your Circle class to make the instance variables
protected instead of private. This lets the subclass
ConcentricCircle have direct access to the instance variables
in Circle.
• Next, code the ShapePanel2 class. In this program you will
call more than just the draw, move, and paint methods.
Sample output is available online.
Abstract Classes
The purpose of abstract classes is to contain the code that will
be the same in subclasses. Therefore, the code doesn’t have
to be repeated over and over again in the subclasses. This
includes instance variables and methods.
If we had thought about this in the beginning, then we could
have created an abstract class immediately and placed all of
the code that is the same in it. An abstract class also tells
subclasses which methods they must have code for.
Here is the code that Circle, Rectangle, and Triangle have in
common:
instance variables: xPos, yPos, color
accessor methods: getXPos, getYPos, and getColor
Let’s look at our Shape Hierarchy with the AbstractShape class
added and then we will continue this discussion.
The Shape 3 Program Heirarchy
Object Class
Shape Interface
AbstractShape
Class
Circle Class
Rectangle Class
ConcentricCircle
Class
Triangle Class
ShapePanel
means implements
means extends
ShapeApplet
means uses
The Shape 3 Hierarchy Explanation
• Notice now that the AbstractShape class is the only class to
implement the Shape interface and that Circle, Rectangle,
and Triangle now extend AbstractShape. This is necessary if
we are going to put all of the code that is the same in
AbstractShape.
• The class definition lines for the four files are now:
abstract public class AbstractShape implements Shape
public class Circle extends AbstractShape
public class Rectangle extends AbstractShape
public class Triangle extends AbstractShape
Is-A Relationships of Shape 3
Because of the class definition lines:
abstract public class AbstractShape implements Shape
public class Circle extends AbstractShape
public class Rectangle extends AbstractShape
public class Triangle extends AbstractShape
public class ConcentricCircle extends Circle
Now we can say that …
a Circle “is a” AbstractShape
a Rectangle “is a” AbstractShape
a Triangle “is a” AbstractShape
a ConcentricCircle “is a” AbstractShape
a ConcentricCircle “is a” Circle
or
has-A Relationships of Shape 3
Now we can still say …
ShapePanel3 “has a” Shape (four of them)
In fact, it has 4 shapes … a Circle, a Rectangle, a Triangle, and
a ConcentricCircle because there are Shape variables s1, s2,
s3 and s4 that refer to constructed Circle, Rectangle, Triangle,
and ConcentricCircle objects.
So we can still say that
ShapePanel3 “has a” Circle
ShapePanel3 “has a” Rectangle
ShapePanel3 “has a” Triangle
ShapePanel3 “has a” ConcentricCircle
Details About Abstract Classes
• Even though an abstract class may have constructors, you
cannot construct an object of an Abstract class using
something like:
Shape s1 = new AbstractShape( );
If you do this Java will give you a compile error.
Think about that. Why would we want to construct a “skeleton”
shape object that doesn’t have the specific information for
either a Circle, Rectangle, or Triangle? We wouldn’t!
Let’s look at some of the code of the AbstractShape class and
explain some things ….
Details About the AbstractShape Class
abstract public class AbstractShape implements Shape
{
protected int xPos;
// instance variables common to all subclasses
protected int yPos;
protected Color color;
static private int shapeCount;
// class variable to track the number of shapes
public AbstractShape ()
{
xPos = 0;
yPos = 0;
color = Color.black;
shapeCount++;
}
// this constructor executed when super();
// is called from any subclass
public AbstractShape (int xLoc, int yLoc, Color c)
{
xPos = xLoc;
// this constructor executed when super(xLoc, yLoc, c);
yPos = yLoc;
// is called from any subclass
color = c;
shapeCount++;
}
Details About the AbstractShape Class
After the constructors, we find this code … the code that was exactly the same
in the Circle, Rectangle, and Triangle classes. We have to make sure we
comment out this code in the three classes, because we now only need it
here.
public int getXPos()
{
return xPos;
}
public int getYPos()
{
return yPos;
}
public Color getColor()
{
return color;
}
Details About the AbstractShape Class
Next, we find five method signatures that are preceded by the word abstract
and all end in a semicolon. The code for these methods MUST be
implemented in the subclasses Circle, Rectangle, and Triangle. We want
the code to be written there because the code for each one is different for
Circle, Rectangle, and Triangle. Making a method abstract is a way of
forcing subclasses to provide code for a method.
abstract public double area();
abstract public void draw (Graphics g);
abstract public void paint (Graphics g);
abstract public void move (int xLoc, int yLoc);
abstract public void stretchBy (int factor);
Note: the subclasses of an abstract class are referred to as concrete classes.
So now with the Shape 3 hierarchy Circle, Rectangle, and Triangle are
concrete classes.
The Java Object Class
All classes in Java can explicitly extend only one class as in ….
public class Circle extends AbstractShape
but they also implicitly extend the Object class.
Its like the class definition line is
public class Circle extends AbstractShape extends Object
but you can’t write this in Java or it will complain.
It is possible but totally unnecessary to include extends Object in
a class definition line if the class does not already extend
another class as in ...
public class ArrayListProcessor3 extends Object
but why would you want to waste time typing it? We mention it
because you might see it. Just don’t assume anything special
is happening if you see it in a class definition line.
The Java Object Class
Here is what several sources say about the Object class:
• Class Object is the root of the class hierarchy. Every class has
Object as a superclass. All objects, including arrays,
implement the methods of this class. (You only need to know
that the Object class has an equals() and a toString() method.)
• The Object class sits at the top of the class hierarchy tree in
the Java development environment. Every class in the Java
system is a descendent (direct or indirect) of the Object class.
The Object class defines the basic state and behavior that all
objects must have, such as the ability to compare oneself to
another object and to convert to a string.
Implementing more than one Java Interface
A final important fact about Java classes is that they can
implement more than one interface. For example:
public class MyGame extends JApplet implements ActionListener, implements MouseListener
is a valid Java class definition line.
Note the comma in
between the
implements clauses.
Coding the Shape 3 Program
• The AbstractShape class is complete. There is no
code to write. We will examine the code.
• Next, we will comment out the code in the Circle,
Rectangle, and Triangle classes that is common to
all three classes that has been transferred to the
AbstractShape class.
• Next, we will discuss “Class Constants”, “Class
(static) Methods”, and “Class Variables”.
• Finally, you will write the code in the ShapePanel3
class. Sample output is available online.
Polymorphism
It is difficult for any programmer to remember the names of
methods in many different classes. So interfaces help by
requiring us to call the methods by certain names with a
specific method signature.
So instead of progammers having to remember separate method
names like:
drawCircle(g) for the Circle class and
drawRectangle(g) for the Rectangle class
They just have to remember draw(g) because that is what the
interface says to call the method!!!
This is extremely helpful to programmers and promotes the
efficient coding of programs and Java will know which draw
method to execute because of the kind of object that makes
the call of the method! This is polymorphism!
Polymorphism
Technically, polymorphism is a superclass reference to a
subclass object, so if a driver file uses the code:
List <Shape> shapes = new ArrayList <Shape> ( );
and
Shape s1 = new Circle (100, 100, 75, Color.blue);
shapes .add(s1);
Shape s2 = new Rectangle (25, 25, 75, 50, Color.red);
shapes .add(s2);
Shape s3 = new Triangle (0, 0, 50, 0, 25, 25, Color.red);
shapes .add(s3);
where s1, s2, and s3 are superclass references to subclass
objects (because they are declared of type Shape), then ……..
(see next slide)
Polymorphism
… when an enhanced for loop draws all of the shapes with the
loop variable element … then element is the superclass
reference to a subclass object, because element gets each
shape out of the list, but Java really knows what kind of
subclass object it was constructed as, so it then knows which
class to go to, so that it can execute the draw(g) method.
for (Shape element: shapes)
{
element.draw(g);
}
The same is true if you were not using an enhanced for loop …
Polymorphism
for (int i = 0; i < shapes.size(); i++)
{
shapes.get(i).draw(g);
}
shapes.get(i) obtains one of the shapes in the list.
shapes.get(i) represents a shape that is a superclass reference
to a subclass object. So again, Java knows exactly what
kind of object the shape really is and it knows which class to
go to, so it can execute the draw(g) method.
Summarizing Inheritance
• If more than one class implements an interface, its methods
are polymorphic.
• A class can implement other methods in addition to those
listed in an interface it implements.
• All classes are part of a large class hierarchy with the
Object class as the root.
• In Java, each class inherits variables and methods of the
classes above it in the hierarchy.
• A class immediately above a class is a superclass.
• A class immediately below a class is a subclass.
• A subclass can add new variables, add new methods, or
alter (override) existing inherited methods.
• All classes defined by programmers automatically extend the
Object class implicitly. There is no need to include extends
Object in a class definition line.
Download