370 likes | 495 Views
Chapter 10. Object-Oriented Programming Part 3B: Polymorphism. abstract Classes and Methods. An abstract class is a class that is not completely implemented. Usually, the abstract class contains at least one abstract method .
E N D
Chapter 10 Object-Oriented Programming Part 3B: Polymorphism
abstract Classes and Methods An abstract class is a class that is not completely implemented. Usually, the abstract class contains at least one abstract method. • An abstract method specifies an API but does not provide an implementation. • The abstract method is used as a pattern for a method the subclasses should implement.
Abstract Classes • An abstract class often contains abstract methods with no definitions (like an interface) • Unlike an interface, the abstract modifier must be applied to each abstract method • Also, an abstract class typically contains non-abstract methods with full definitions • A class declared as abstract does not have to contain abstract methods -- simply declaring it as abstract makes it so
Abstract Classes • The child of an abstract class must override the abstract methods of the parent, or it too will be considered abstract • An abstract method cannot be defined as final or static • The use of abstract classes is an important element of software design – it allows us to establish common elements in a hierarchy that are too generic to instantiate
More on abstract Classes An abstract class cannot be used to instantiate objects (because the class is not complete). However, an object reference to an abstract class can be declared. • We use this capability in polymorphism, discussed later. An abstract class can be extended. • subclasses can complete the implementation. Objects of those subclasses can be instantiated.
Defining an abstract Class To declare a class as abstract, include the abstract keyword in the class header: accessModifier abstract class ClassName { // class body }
Defining an abstract Method To declare a method as abstract, include the abstract keyword in the method header, and end the header with a semicolon: accessModifier abstract returnType methodName( argument list ); Note: • The semicolon at the end of the header indicates that the method has no code. • We do not use opening and closing curly braces { }.
Example Hierarchy We can define a Figurehierarchy. • The superclass is Figure,which is abstract. (In theUML diagram, Figure is set in italics to indicate that it is abstract.) • We will derive two non-abstract subclasses: Circle andSquare.
The Figure Class public abstract class Figure { private int x; private int y; private Color color; // usual constructors, accessors, // and mutators // abstract draw method public abstract void draw( Graphics g ); } All classes in the hierarchy will have an (x, y) coordinate and color. Subclasses will implement the draw method.
Subclasses of abstract Classes • A subclass of an abstract class can implement all, some, or none of the abstract methods. • If the subclass does not implement all of the abstract methods, it must also be declared as abstract. • Our Circle subclass adds a radius instance variable and implements the draw method. • Our Square subclass adds a length instance variable and implements the draw method. See Examples 10.15, 10.16, 10.17, & 10.18
Example 10.15 import java.awt.Graphics; import java.awt.Color; public abstract class Figure { private int x; private int y; private Color color; /** default constructor sets x and y to 0 sets color to black */ public Figure( ) { x = 0; y = 0; color = Color.BLACK; } /** overloaded constructor sets x to startX sets y to startY sets the color to startColor * @param startX starting x pixel for figure * @param startY starting y pixel for figure * @param startColor figure color */ public Figure( int startX, int startY, Color startColor ) { x = startX; y = startY; color = startColor; }
/** accessor method for color @return current figure color */ public Color getColor( ) { Color tempColor = color; return tempColor; } /** mutator method for color @param newColor new color for figure */ public void setColor( Color newColor ) { color = newColor; } /** accessor method for x @return current x value */ public int getX( ) { return x; } /** mutator method for x @param newX new value for x */ public void setX( int newX ) { x = newX; } /** accessor method for y @return current y value */ public int getY( ) { return y; } /** mutator method for y @param newY new y value */ public void setY( int newY ) { y = newY; } /** abstract draw method @param Graphics context for drawing figure */ public abstract void draw( Graphics g ); /** abstract area method @return returns area for figure */ public abstract double area ( ); }
Example 10.16 import java.awt.Graphics; import java.awt.Color; public class Circle extends Figure { private int radius; /** default constructor calls default constructor of Figure class * sets radius to 0 */ public Circle( ) { super( ); radius = 0; }
/** overloaded constructor * sends startX, startY, startColor to Figure constructor * sends startRadius to setRadius method * @param startX starting x pixel * @param startY starting y pixel * @param startColor color for circle * @param startradius radius of circle */ public Circle( int startX, int startY, Color startColor, int startRadius ) { super( startX, startY, startColor ); setRadius( startRadius ); } /** mutator method for radius @param newRadius new value for radius */ public void setRadius( int newRadius ) { radius = newRadius; } /** accessor method for radius @return radius */ public int getRadius( ) { return radius; }
/** draw method sets color and draws a circle * @param g Graphics context for drawing the circle */ public void draw( Graphics g ) { g.setColor( getColor( ) ); g.fillOval ( getX( ), getY( ), radius * 2, radius * 2 ); } /** area method public double area ( ) { return Math.pi() * radius * radius; } }
Example 10.17 import java.awt.Graphics; import java.awt.Color; public class Square extends Figure { private int length; /** default constructor calls default constructor of Figure class * sets length to 0 */ public Square( ) { super( ); length = 0; }
/** overloaded constructor * sends startX, startY, startColor to Figure constructor * sets startLength to setLength method * @param startX starting x pixel * @param startY starting y pixel * @param startColor color for square * @param startlength length of square */ public Square( int startX, int startY, Color startColor, int startLength ) { super( startX, startY, startColor ); setLength( startLength ); } /** mutator method for length @param newLength new value for length */ public void setLength( int newLength ) { length = newLength; }
/** accessor method for length @return length */ public int getLength( ) { return length; } /** draw method sets color and draws a square * @param g Graphics context for drawing the square */ public void draw( Graphics g ) { g.setColor( getColor( ) ); g.fillRect( getX( ), getY( ), length, length ); } /** area method public double area ( ) { return length * length; } }
Example 10.18 import javax.swing.JApplet; import java.awt.*; import java.util.ArrayList; public class TrafficLight extends JApplet { private ArrayList<Circle> circlesList; private ArrayList<Square> squaresList; public void init( ) { squaresList = new ArrayList<Square>( ); squaresList.add( new Square( 150, 100, Color.BLACK, 40 ) ); squaresList.add( new Square( 150, 140, Color.BLACK, 40 ) ); squaresList.add( new Square( 150, 180, Color.BLACK, 40 ) ); circlesList = new ArrayList<Circle>( ); circlesList.add( new Circle( 160, 110, Color.RED, 10 ) ); circlesList.add( new Circle( 160, 150, Color.YELLOW, 10 ) ); circlesList.add( new Circle( 160, 190, Color.GREEN, 10 ) ); }
public void paint( Graphics g ) { for ( Square s : squaresList ) s.draw( g ); for ( Circle c : circlesList ) c.draw( g ); } }
Restrictions for Defining abstract Classes • Classes must be declared abstract if the class contains any abstract methods. • abstract classes can be extended. • abstract classes cannot be used to instantiate objects. • An object reference to an abstract class can be declared.
Restrictions for Defining abstract Methods • abstract methods can be declared only within an abstract class. • An abstract method must consist of a method header followed by a semicolon. • abstract methods cannot be called. • abstract methods cannot be declared as private or static. • A constructor cannot be declared abstract.
Multiple Inheritance • Java supports single inheritance, meaning that a derived class can have only one parent class • Multiple inheritance allows a class to be derived from two or more classes, inheriting the members of all parents • One problem with multiple inheritance is collisions, such as the same variable name in two parents, which has to be resolved • Java does not support multiple inheritance • In most cases, the use of interfaces gives us aspects of multiple inheritance without the overhead
Polymorphism An important concept in inheritance is that an object of asubclass is also an object of any of its superclasses. • That concept is the basis for an important OOP feature, called polymorphism. • Polymorphism simplifies the processing of various objects in the same class hierarchy because we can use the same method call for any object in the hierarchy using a superclass object reference.
Example Hierarchy • Consider thishierarchy • The superclass is Figure,which defines a method called doIt() • One of two subclasses redefines doIt() • If I have a variable v and say v.doIt() which method is called? doIt() doIt()
Binding • Consider the following method invocation: obj.doIt(); • At some point, this invocation is bound to the definition of the method that it invokes • If this binding occurred at compile time, then that line of code would call the same method every time • However, Java defers method binding until run time -- this is called dynamic binding or late binding • Late binding provides flexibility in program design
Polymorphism • The term polymorphism literally means "having many forms" • A polymorphic reference is a variable that can refer to different types of objects at different points in time • The method invoked through a polymorphic reference can change from one invocation to the next • All object references in Java are potentially polymorphic
Polymorphism • Suppose we create the following reference variable: Occupation job; • Java allows this reference to point to an Occupation object, or to any object of any compatible type • This compatibility can be established using inheritance or using interfaces • Careful use of polymorphic references can lead to elegant, robust software designs
References and Inheritance • Assigning a child object to a parent reference is considered to be a widening conversion, and can be performed by simple assignment • Assigning an parent object to a child reference can be done also, but it is considered a narrowing conversion and must be done with a cast • The widening conversion is the most useful Widening – int to double Narrowing – double to int
Polymorphism via Inheritance • It is the type of the object being referenced, not the reference type, that determines which method is invoked (donut hole type, not variable type) • Suppose the Holiday class has a method called celebrate, and the Christmas class overrides it
Holiday Christmas Birthday President’s Mine Polymorphism via Inheritance
Polymorphism via Inheritance • Now consider the following invocation: day.celebrate(); • If day refers to a Holiday object, Holiday day; day.celebrate(); it invokes the Holiday version of celebrate; • If it refers to a Christmas object, Christmas day; day.celebrate(); it invokes the Christmas version
Holiday Christmas References and Inheritance • An object reference can refer to an object of its class, or to an object of any class related to it by inheritance • For example, if the Holiday class is used to derive a class called Christmas, then a Holiday reference could be used to point to a Christmas object Holiday day; day = new Christmas();
Polymorphism Requirements To use polymorphism, these conditions must be true: • the classes are in the same hierarchy. • all subclasses override the target method. • a subclass object reference is assigned to a superclass object reference. • the superclass object reference is used to call the target method.
Example Example 10.19 shows how we can simplify the drawing of Circle and Square objects. We instantiate a FigureArrayList and add Circle and Square objects to it. ArrayList<Figure> figuresList = new ArrayList<Figure>( ); figuresList.add( new Square( 150, 100, Color.BLACK, 40 ) ); figuresList.add( new Circle( 160, 110, Color.RED, 10 ) ); … In the paint method, we call draw for each Figure: for ( Figure f : figuresList ) f.draw( g );
Polymorphism Conditions Example 10.19 shows that we have fulfilled the conditions for polymorphism: • The Figure, Circle, and Square classes are in the same hierarchy. • The non-abstractCircle and Square classes implement the draw method. • We assigned the Circle and Square objects to Figure references. • We called the draw method using Figure references.