You are on page 1of 7

Chapter Four

Polymorphism
 Polymorphism allows programmers to send the same message to objects from different classes. i.e., in
its simplest form, polymorphism allows a single variable to refer to objects from different classes.

 Polymorphism enables us to “program in the general” rather than “program in the specific”. In
particular, polymorphism enables us to write programs that process objects of classes that are part of
the same class hierarchy as if they are all objects of their classes.

 With polymorphism, it is possible to design and implement systems that are easily extensible. New
classes can be added with little or no modification to the generic portions of the program, as long as
those classes are part of the inheritance hierarchy that the program processes generically. The only parts
of a program that must be altered to accommodate new classes are those program components that
require direct knowledge of the new classes that the programmer adds to the
hierarchy.

Relationships among Objects in an inheritance hierarchy


 Here, we will examine the relationships among classes in a hierarchy. In this section, we see that an
object of a subclass can be treated as object of its superclass. This enables various interesting
manipulations. For example, a program can create an array of superclass reference that refers to objects
of many subclass types. This is allowed despite that fact that the subclass objects are of
different types, because each subclass object is an object of its superclass.
However, a superclass object is not an object of any of its subclasses. The “is-a” relationship applies
only from a subclass to its direct and indirect superclasses.

Assigning reference of a subclass to a superclass-type variable


 Let us see an example here:
public class Point{
private int x;
private int y;
public Point(int xValue,int yValue)
{
x=xValue;
y=yValue;
}
//getters and setters
//to string method
}//end class

public class Circle extends Point{


private double radius;
public Circle4(int xValue, int yValue, double rValue)
{
super(xValue,yValue);
this .Value=rValue;

1
}
public double getDiameter()
{
return 2*getRadius();
}
public double getCircumfrence()
{
return Math.PI*getDiameter();
}
public double getArea()
{
return Math.PI*getRadius()*getRadius();
}
public String toString()
{
return “Center = “+super.toString()+ “; Radius=”+getRadius();
}
}//end class

import javax.swing.*;
public class PolyTest1{
public static void main(String args[])
{
Point point = new Point(30,50);
Circle circle = new Circle(120,89,2.7);
String output = “Call Point’s toString with superclass”+“reference to superclass object:\n”+
point.toString();
output+= “\n\nCall Circle’s toString with subclass ”+“reference to subclass object:\n”+circle.toString();
Point pointRef = circle;
Output+= “\n\ncall Circle’s toString with superclass ”+“ refernce to subclass object:\n
“+pointRef.toString();
JOptionPane.showMessageDialog(null,output);
System.exit(0);
}
}//end class

 In the above program, the statement Point pointRef = circle; assigns the reference of subclass object
circle to superclass-type variable pointRef. A superclass-type variable that contains a reference to a
subclass object calls the subclass method; hence, pointRef.toString() actually calls class Circle’s
toString method. The Java compiler allows this “crossover” because an object of a subclass is an object
of its superclass.

Assigning a superclass object’s reference to a subclass-type variable


 Let us consider the following example:
public class PolyTest2{
public static void main(String args[])

2
{
Point3 point = new Point3(30,50);
Circle4 circle;//subclass-type variable
//assign superclass reference to subclass-type variable
circle = point;
}
}//end class
 If you run this program, it will generate an error. Because the assignment is not allowed (incompatible
type). The Java compiler prevents this assignment, because a Point3 is not a Circle4- the “is-a”
relationship applies only between the subclass and its superclass.

 It turn out that the Java compiler does allow this assignment if we explicitly cast the superclass
reference to the subclass type. In programs that process superclass and subclass objects by using
superclass reference, only methods of the superclass can be invoked via the superclass reference.
Casting superclass reference to subclass reference (also known as downcasting) enables a program to
invoke subclass functionality to perform subclass-specific operations on subclass objects.
N.B. assigning the reference of a superclass object to a subclass-type variable
(without an explicit cast) is a compile-time error

Subclass Method calls via superclass-type variables


 Consider the following program:
public class PolyTest3{
public static void main(String args[])
{
Point3 point;
Circle circle = new Circle4(120,89,2.7);
point = circle;//aim superclass reference at subclass object.
int x = point.getX();
int y = point.getY();
point.setX(10);
point.setY(20);
point.toString();
//attempt to invoke subclass-only (Circle4) method on
//subclass object through superclass (Point3) reference
double radius = point.getRadius();
point.setRadius(33.33);
double diameter = point.getDiameter();
double circumference = point.getCircumfrence();
double area = point.getArea();
}
}//end class
 In the above code, we have such an assignment: point = circle; Java compiler allows this because a
Circle4 is a Point3 object. Using point reference, we can only invoke superclass only methods. But
when we try to invoke subclass only methods using point, the Java compiler generates error on each of
these lines, because these are not methods of the superclass Point3. (in this case, using a Point3
variable, we can invoke only Point3 methods getX, getY, setX, setY and

3
toString)

Summary of the allowed assignments between superclass and subclass variables


 Despite the fact that a subclass object also is a superclass object, the subclass and superclass objects
are indeed different. As we have discussed previously, subclass objects can be treated as if they were
superclass objects. This is a logical relationship, because the subclass contains all the members of the
superclass, but the subclass can have additional subclass-only members. For this reason, assigning a
superclass reference to a subclass-type variable is not allowed without
an explicit cast; such an assignment would leave the subclass-only members undefined for the subclass
object.

 We have discussed four ways to assign superclass and subclass references to variables of superclass
and subclass types:
1. Assigning a superclass reference to a superclass-type variable is straight forward
2. Assigning a subclass reference to a subclass-type variable is straight forward.
3. Assigning a subclass object’s reference to a superclass type variable is safe, because
the subclass object is an object of its superclass. However, this reference can be used to invoke only
superclass methods. If this code refers to subclass-only members through the superclass variable,
the compiler generates an error.
4. Attempting to assign a superclass object’s reference to a subclass type variable is a
compile-time error. To avoid the error, the superclass reference must be cast to a
subclass type explicitly.

Multiple inheritance and Interfaces


 An interface is like a class that can’t be instantiated. Its purpose is to specify a set of requirements
for a class to implement. These requirements are regarded as a “contract” between the implementing
class and any client class that uses it.

 An interface is a description of a capability. It lists the methods that a class must implement to
carry out that capability.

 An interface typically consists of declarations of related methods, although an interface also may
contain static and final fields that represent constants. In any case, all interface members are public.
A class that implements an interface typically provides definitions for the methods declared in the
interface.
A class that implements an interface must provide an implementation for all the method signatures in
the interface. An interface declaration introduces a new reference type whose members are constants
and abstract methods.

 An interface is typically used in place of an abstract class when there is no default


implementation to inherit. i.e., no instance variables and no default methods implementations.

 A compile-time error occurs if the identifier naming an interface appears as the name of any other
class or interface in the same package.
 All interface methods are abstract regardless of whether the term abstract occurs. In more basic
terms, an interface is abstract because an interface can’t be instantiated as an object.

4
 Let us see an example here:
public interface Shape{
public double getArea();
public double getVolume();
public String getName();
}//end interface
public class Point extends Object implements Shape{
private int x;
private int y;
public Point(int xValue,int yValue)
{
x = xValue;
y = yValue;
}
public void setX(int xValue)
{
x=xValue;
}
public void setY(int yValue)
{
y=yValue;
}
public int getX()
{
return x;
}

public int getY()


{
return y;
}
public double getArea()
{
return 0.0;
}
public double getVolume()
{
return 0.0;
}
public String getName()
{
return “Point”;
}
public String toString()
{

5
return “[”+getX()+ “, ”+getY()+ “]”;
}
}//end class
Use the Circle4 program and the following Cylinder class for the coming illustration
public class Cylinder extends Circle4{
private double height;
public Cylinder(int x,int y,double radius,double heightValue)
{
super(x,y,radius);
setHeight(heightValue);
}
public void setHeight(double heightValue)
{
height = (heightValue <0.0?0.0:heightValue);
}
public double getHeight()
{
return height;
}
public double getArea()
{
return 2 * super.getArea() + getCircumfrence() * getHeight();
}
public double getVolume()
{
return super.getArea() * getHeight();
}
public String getName()
{
return “Cylinder”;
}
public String toString()
{
return super.toString()+ “; Height = ” + getHeight();
}
}//end class

import javax.swing.*;
import java.text.*;
public class InterfaceTest{
public static void main(String args[])
{
DecimalFormat twoDigits = new DecimalFormat(“0.00”);
Point point =new Point(7,11);
Circle4 circle = new Circle4(22,8,3.5);
Cylinder cylinder = new Cylinder(20,30,3.3.3,10.75);

6
String output = point.getName()+ “:”+point+ “\n”+ circle.getName() +
“:”+circle+ “\n”+ cylinder.getName() + “:”+cylinder+ “\n”;
Shape arrayOfShapes[] = new Shape[3];//create shape array
arrayOfShape[0] = point;
arrayOfShape[1] = circle;
arrayOfShape[2] = cylinder;
for(int i=0; i<arrayOfShapes.length;i++)
{
output += ”\n\n ”+arrayOfShapes[i].getName()+ “:” +
arrayOfShapes[i].toString()+ “\nArea =
”+twoDigits.format(arrayOfShapes[i].getArea())+ “\nVolume = ”+
twoDigits.format(arrayOfShapes[i].getVolume());
}
JOptionPane.showMessageDialog(null,output);
System.exit(0);
}
}//end class
 When a class implements an interface, the same “is-a” relationship provided by inheritance applies.
For example, class Point implements Shape. Therefore, a Point object is a Shape. In fact, objects of
any class that extends Point are also Shape object.
Multiple inheritances
 A class can be derived from more than one superclass. This concept is called multiple inheritance.
But such a notion can’t be directly used in Java. Therefore, one has to use an interface if a class is
expected to inherit behaviors from more than one superclass. For instance, Let us see the
declaration of class Point:
public class Point extends Object implements Shape{
}//end class
 In Java, all classes inherit from class Object. So whether we write the statement “Point extends
Object” or not, the Java compiler processes the inheritance relationship among Point and Object
classes. Therefore, our class Point will have both the functionality of class Object and that of Shape,
hence multiple inheritance. The point to be underlined here is, multiple inheritance is only possible
through the use of interfaces.
 To summarize the discussion of interface; lets see the following comparison.
Unlike a class, an interface:
 Declares only method headers and public constants;
 Has no constructors
 Can’t be instantiated
 Can be implements by a class
 Can’t be implemented by an interface
 Can’t extends a class
 Can extend several other interfaces.
 Interface are very useful for specifying what a class should be able to do, while deferring to a later
time how the contract should be implemented. But in some cases, interfaces are too restrictive.
They allow no variable definitions (except public final constants) or executable statements. Often, it
is better to proceed with a partial class implementation, deferring only those methods that depend
directly upon the backing data structure. That is when an abstract class should be used.

You might also like