Newsletter sign-up
View all newsletters

Enterprise Java Newsletter
Stay up to date on the latest tutorials and Java community news posted on JavaWorld

Sponsored Links

Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs

Object-oriented language basics, Part 7

Learn about Java's many shapes and find out how to accommodate generalities in your class hierarchies

  • Print
  • Feedback

Page 5 of 7

Listing 4. Cats1.java

// Cats1.java
class Cat
{
   String getInfo ()
   {
      return "?";
   }
}
class Lion extends Cat
{
   String getInfo ()
   {
      return "king of the jungle";
   }
}
class Cheetah extends Cat
{
   String getInfo ()
   {
      return "great speed";
   }
}
class Tiger extends Cat
{
   String getInfo ()
   {
      return "has stripes";
   }
}
class Cats1
{
   public static void main (String [] args)
   {
      Cat [] cats =
      {
         new Lion (),
         new Cheetah (),
         new Tiger (),
         new Cat ()
      };
      for (int i = 0; i < cats.length; i++)
           System.out.println (cats [i].getInfo ());
   }
}


Cats1 presents three hierarchies of cat-related classes. At the top of those hierarchies sits a Cat class. Even though that class is basically empty, its purpose is to extract commonality found among all cats. Cats1 confines that commonality to a single getInfo() method, and subclasses override getInfo() to return cat-specific information.

Cats1's main() method declares an array of Cat objects and assigns a new Cat object to each entry. It makes sense to create Lion, Cheetah, and Tiger objects, because those objects represent specific kinds of cats. But does it also make sense to create a Cat object and assign its reference to an array entry? Does Cat represent a specific kind of cat? I think not. My opinion stems from the following Cats1 output:

king of the jungle
great speed
has stripes
?


That final ? signifies the output from calling Cat's getInfo() method. The question mark indicates that the code cannot provide specific information about something so generic. Ideally, you do not want such a situation to crop up in your class hierarchies.

Fortunately, Java provides a way to prevent object creation from generic classes. Prefixing a class signature with the abstract keyword results in an abstract class. Any attempt to create an object from an abstract class causes a compiler error. Listing 5's Cats2 source code demonstrates an abstract class declaration:

Listing 5. Cats2.java

// Cats2.java
abstract class Cat
{
   abstract String getInfo ();
}
class Lion extends Cat
{
   String getInfo ()
   {
      return "king of the jungle";
   }
}
class Cheetah extends Cat
{
   String getInfo ()
   {
      return "great speed";
   }
}
class Tiger extends Cat
{
   String getInfo ()
   {
      return "has stripes";
   }
}
class Cats2
{
   public static void main (String [] args)
   {
      Cat [] cats =
      {
         new Lion (),
         new Cheetah (),
         new Tiger (),
//         new Cat ()
      };
      for (int i = 0; i < cats.length; i++)
           System.out.println (cats [i].getInfo ());
   }
}


Cats2 prefixes the Cat class signature with keyword abstract. To prove that you cannot create an object from Cat, uncomment the new Cat () line in the above cats array declaration and attempt to compile. You will receive a compiler error message.

Cats2 also demonstrates an abstract method: Cat's getInfo(). Prefixing a method signature with keyword abstract accomplishes the following tasks:

  1. Signifies that the method has no associated code body
  2. Indicates that the class declaring that method must have a class signature prefixed by keyword abstract
  3. Indicates that any subclass inheriting but not overriding that method is automatically regarded as abstract


You introduce an abstract method into an abstract class when that method identifies a common behavior that manifests itself (in subclasses) in different ways. For example, the get-information behavior found in Cats2 manifests itself somewhat differently in the Lion, Cheetah, and Tiger subclasses. Although each method currently returns a different string literal, you might change each method to contain additional logic unique to its class. Also, an abstract method's presence in an abstract superclass allows you to assign a subclass object reference to the superclass object reference variable and (through inclusion/subtype polymorphism) call the more specific subclass method.

  • Print
  • Feedback

Resources