710 likes | 852 Vues
Chapter 10 Part 2. Object-Oriented Programming Part 3: Polymorphism, Abstract Classes, and Interfaces. Topics. Polymorphism Abstract Classes and Methods Interfaces. Polymorphism.
E N D
Chapter 10 Part 2 Object-Oriented Programming Part 3: Polymorphism, Abstract Classes, and Interfaces
Topics • Polymorphism • Abstract Classes and Methods • Interfaces
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
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();
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
Polymorphism Requirements • To use polymorphism, these conditions must be true: • the classes are in the same hierarchy. • all subclasses override the same method. • a subclass object reference is assigned to a superclass object reference. • the superclass object reference is used to call the 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 this way: for ( Figure f : figuresList ) f.draw( g );
Example 10.19 public class TrafficLightPolymorphism extends JApplet { private ArrayList<Figure> figuresList; public void init( ) { figuresList = new ArrayList<Figure>( ); figuresList.add( new Square( 150, 100, Color.BLACK, 40 ) ); figuresList.add( new Circle( 160, 110, Color.RED, 10 ) ); figuresList.add( new Square( 150, 140, Color.BLACK, 40 ) ); figuresList.add( new Circle( 160, 150, Color.YELLOW, 10 ) ); figuresList.add( new Square( 150, 180, Color.BLACK, 40 ) ); figuresList.add( new Circle( 160, 190, Color.GREEN, 10 ) ); } public void paint( Graphics g ) { 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-abstract Circle 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.
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 object reference to an abstract class can be declared. • We use this capability in polymorphism. • An abstract class cannot be used to instantiate objects (because the class is not complete). • An abstract class can be extended. • subclasses can complete the implementation and 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: 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 open 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 subclasses: Circle andSquare.
The Figure Class public abstract class Figure { private int x; private int y; private Color color; // usual constructors, accessors, // and mutators that can be implemented // abstract methods public abstract void draw( Graphics g ); public abstract double area( ); } • All classes in the hierarchy will have an (x, y) coordinate and color. Subclasses will implement the draw and area 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 and area methods. • Our Square subclass adds a length instance variable and implements the draw and area methods.
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. • An object reference to an abstract class can be declared. • abstract classes cannot be used to instantiate objects.
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
Interfaces • A class can inherit directly from only one class, that is, a class can extend only one class. • To allow a class to inherit behavior from multiple sources, Java provides the interface. • An interface typically specifies behavior that a class will implement. Interface members can be any of the following: · classes · constants ·abstract methods · other interfaces
Interface Syntax • To define an interface, use the following syntax: accessModifier interface InterfaceName { // body of interface } • All interfaces are abstract; thus, they cannot be instantiated. The abstract keyword, however, can be omitted in the interface definition.
interfaceis a reserved word A semicolon immediately follows each method header Interfaces None of the methods in an interface are given a definition (body) public interface Doable { public void doThis(); public int doThat(); public void doThis2 (float value, char ch); public boolean doTheOther (int num); }
Finer Points of Interfaces • An interface's fields are public, static, and final. These keywords can be specified or omitted. • When you define a field in an interface, you must assign a value to the field. • All methods within an interface must be abstract, so the method definition must consist of only a method header and a semicolon. The abstract keyword also can be omitted from the method definition.
Inheriting from an Interface • To inherit from an interface, a class declares that it implements the interface in the class definition, using the following syntax: accessModifier class ClassName extends SuperclassName implements Interface1, Interface2, … • The extends clause is optional. • A class can implement 0, 1, or more interfaces. • When a class implements an interface, the class must provide an implementation for each method in the interface.
Interfaces • An interface cannot be instantiated • Methods in an interface have public visibility by default • A class formally implements an interface by: • stating so in the class header • providing implementations for each abstract method in the interface • If a class asserts that it implements an interface, it must define all methods in the interface
implementsis a reserved word Each method listed inDoableis given a definition Interfaces public class CanDo implements Doable { public void doThis () { // whatever } public void doThat () { // whatever } // etc. }
Polymorphism via Interfaces • An interface name can be used as the type of an object reference variable Speaker current; • The current reference can be used to point to any object of any class that implements the Speaker interface • The version of speak that the following line invokes depends on the type of object that current is referencing current.speak();
Polymorphism via Interfaces • Suppose two classes, Philosopher and Dog, both implement the Speaker interface, providing distinct versions of the speak method • In the following code, the first call to speak invokes one version and the second invokes another: Speaker guest = new Philospher(); guest.speak(); guest = new Dog(); guest.speak();
Interfaces • The Java standard class library contains many helpful interfaces • The Comparable interface contains one abstract method called compareTo, which is used to compare two objects • We know about the compareTo method of the String class • The String class implements Comparable, giving us the ability to put strings in lexicographic order
The Comparable Interface • Any class can implement Comparable to provide a mechanism for comparing objects of that type if (obj1.compareTo(obj2) < 0) System.out.println ("obj1 is less than obj2"); • The value returned from compareTo should be negative is obj1 is less that obj2, 0 if they are equal, and positive if obj1 is greater than obj2 • When a programmer designs a class that implements the Comparable interface, it should follow this intent
The Comparable Interface • It's up to the programmer to determine what makes one object less than another • For example, you may define the compareTo method of an Employee class to order employees by name (alphabetically) or by employee number • The implementation of the method can be as straightforward or as complex as needed for the situation