There are situations in which you will
want to define a superclass that declares the structure of a given abstraction
without providing a complete implementation of every method. That is, sometimes
you will want to create a superclass that only defines a generalized form that
will be shared by all of its subclasses, leaving it to each subclass to fill in
the details. Such a class determines the nature of the methods that the sub c lasses
must implement.
One way this situation can occur is when a super
class is unable to create a meaningful implementation for a method. This is the
case with the class Figure used in the preceding example. The definition of
area( ) is simply a placeholder. It will not compute and display the area of
any type of object.
As you will see as you create your own
class libraries, it is not uncommon for a method to have no meaningful
definition in the context of its superclass. You can handle this situation two
ways. One way, as shown in the previous example, is to simply have it report a
warning message. While this approach can be useful in certain situations—such
as debugging—it is not usually appropriate. You may have methods which must be
overridden by the subclass in order for the subclass to have any meaning.
Consider the class Triangle. It has no meaning if area( ) is not defined. In
this case, you want some way to ensure that a subclass does, indeed, override
all necessary methods. Java's
solution to this problem is the abstract method.
solution to this problem is the abstract method.
You can require that certain methods be
overridden by subclasses by specifying the abstract type modifier. These
methods are sometimes referred to as subclasser responsibility because they
have no implementation specified in the superclass. Thus, a subclass must
override them—it cannot simply use the version defined in the superclass. To declare
an abstract method, use this general form:
abstract type name(parameter-list);
As you can see, no method body is
present. Any class that contains one or more abstract methods must also be
declared abstract. To declare a class abstract, you simply use the abstract
keyword in front of the class keyword at the beginning of the class
declaration. There can be no objects of an abstract class. That is, an abstract
class cannot be directly instantiated with the new operator. Such objects would
be useless, because an abstract class is not fully defined. Also, you cannot
declare abstract constructors, or abstract static methods. Any subclass of an
abstract class must either implement all of the abstract methods in the
superclass, or be itself declared abstract.
Here is a simple example of a class with an abstract method, followed by a class which implements that method:
Here is a simple example of a class with an abstract method, followed by a class which implements that method:
// A Simple demonstration of abstract.
abstract class A {
abstract void callme();
// concrete methods are still allowed in abstract classes
void callmetoo() {
System.out.println("This is a concrete method.");
}
}
abstract class A {
abstract void callme();
// concrete methods are still allowed in abstract classes
void callmetoo() {
System.out.println("This is a concrete method.");
}
}
class B extends A {
void callme() {
System.out.println("B's implementation of callme.");
}
}
void callme() {
System.out.println("B's implementation of callme.");
}
}
class AbstractDemo {
public static void main(String args[]) {
B b = new B();
b.callme();
b.callmetoo();
}
}
public static void main(String args[]) {
B b = new B();
b.callme();
b.callmetoo();
}
}
Notice that no objects of class A are
declared in the program. As mentioned, it is not possible to instantiate an
abstract class. One other point: class A implements a concrete method called
callmetoo( ). This is perfectly acceptable. Abstract classes can include as
much implementation as they see fit.
Although abstract classes cannot be
used to instantiate objects, they can be used to create object references,
because Java's approach to run-time polymorphism is implemented through the use
of superclass references. Thus, it must be possible to create a reference to an
abstract class so that it can be used to point to a subclass object. You will
see this feature put to use in the next example. Using an abstract class, you can
improve the Figure class shown earlier. Since there is no meaningful concept of
area for an undefined two-dimensional figure, the following version of the
program declares area( ) as abstract inside Figure. This, of course, means that
all classes derived from Figure must override area( ).
// Using abstract methods and classes.
abstract class Figure {
double dim1;
double dim2;
Figure(double a, double b) {
dim1 = a;
dim2 = b;
}
// area is now an abstract method
abstract double area();
}
abstract class Figure {
double dim1;
double dim2;
Figure(double a, double b) {
dim1 = a;
dim2 = b;
}
// area is now an abstract method
abstract double area();
}
class Rectangle extends Figure {
Rectangle(double a, double b) {
super(a, b);
}
// override area for rectangle
double area() {
System.out.println("Inside Area for Rectangle.");
return dim1 * dim2;
}
}
Rectangle(double a, double b) {
super(a, b);
}
// override area for rectangle
double area() {
System.out.println("Inside Area for Rectangle.");
return dim1 * dim2;
}
}
class Triangle extends Figure {
Triangle(double a, double b) {
super(a, b);
}
// override area for right triangle
double area() {
System.out.println("Inside Area for Triangle.");
return dim1 * dim2 / 2;
}
}
Triangle(double a, double b) {
super(a, b);
}
// override area for right triangle
double area() {
System.out.println("Inside Area for Triangle.");
return dim1 * dim2 / 2;
}
}
class AbstractAreas {
public static void main(String args[]) {
// Figure f = new Figure(10, 10); // illegal now
Rectangle r = new Rectangle(9, 5);
Triangle t = new Triangle(10, 8);
Figure figref; // this is OK, no object is created
figref = r;
System.out.println("Area is " + figref.area());
figref = t;
System.out.println("Area is " + figref.area());
}
}
public static void main(String args[]) {
// Figure f = new Figure(10, 10); // illegal now
Rectangle r = new Rectangle(9, 5);
Triangle t = new Triangle(10, 8);
Figure figref; // this is OK, no object is created
figref = r;
System.out.println("Area is " + figref.area());
figref = t;
System.out.println("Area is " + figref.area());
}
}
As the comment inside main( )
indicates, it is no longer possible to declare objects of type Figure, since it
is now abstract. And, all subclasses of Figure must override area( ). To prove
this to yourself, try creating a subclass that does not override area( ). You
will receive a compile-time error.
Although it is not possible to create
an object of type Figure, you can create a reference variable of type Figure.
The variable figref is declared as a reference to Figure, which means that it can
be used to refer to an object of any class derived from Figure. As explained,
it is through superclass reference variables that overridden methods are
resolved at run time.