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 3 of 7

Listing 1 shows how Java statically binds class method calls to classes at compile time:

Listing 1. SMB.java

// SMB.java
class Superclass
{
   static void method ()
   {
      System.out.println ("Superclass method");
   }
}
class Subclass extends Superclass
{
   static void method ()
   {
      System.out.println ("Subclass method");
   }
}
class SMB
{
   public static void main (String [] args)
   {
      Superclass sc = new Superclass ();
      sc.method ();
      sc = new Subclass ();
      sc.method ();
   }
}


SMB declares a class hierarchy consisting of Superclass and Subclass classes. Each of those classes declares a class method named method(). A third class, SMB, declares a main() method that does the following:

  1. Creates a Superclass object
  2. Assigns that object's reference to sc
  3. Calls method() by (apparently) using sc's reference
  4. Creates a Subclass object
  5. Assigns that object's reference to sc
  6. Calls method() by (apparently) using sc's reference


When run, SMB produces the following output:

Superclass method
Superclass method


The output might surprise you, but remember that class methods associate with classes, not objects. Even though SMB's sc.method() calls give the impression that main() calls instance methods, main() calls only a single method() statically bound to Superclass. SMB's main() method could just as easily achieve the same output by replacing main()'s code with two consecutive Superclass.method (); calls. As a result, inclusion/subtype polymorphism does not exist with statically bound method calls. (Note: Calling class methods via object reference variables is not wise because it clouds the fact that those methods are class methods.)

Contrary to how Java treats class methods, Java dynamically binds instance method calls to objects at runtime, making inclusion/subtype polymorphism possible. Listing 2 demonstrates this:

Listing 2. DMB1.java

// DMB1.java
class Superclass
{
   void method ()
   {
      System.out.println ("Superclass method");
   }
}
class Subclass extends Superclass
{
   void method ()
   {
      System.out.println ("Subclass method");
   }
}
class DMB1
{
   public static void main (String [] args)
   {
      Superclass sc = new Superclass ();
      sc.method ();
      sc = new Subclass ();
      sc.method ();
   }
}


DMB1's source code is nearly identical to SMB's source code. Apart from its class name, DMB1 only differs in the absence of the static keyword from the method() signatures in Superclass and Subclass. When run, DMB1 outputs the following:

Superclass method
Subclass method


DMB1's output differs from SMB1's because the JVM dynamically locates the correct method() to call based on the object reference appearing in sc. In the first method() call, the JVM uses the Superclass object reference it retrieved from sc to locate Superclass's method(). In the second method() call, the JVM uses the Subclass object reference it retrieved from sc to locate Subclass's method(). And that is inclusion/subtype polymorphism at work.

Because Java dynamically binds instance method calls to objects at runtime, you can use inclusion/subtype polymorphism with either a single class hierarchy or with interfaces that extract commonality from multiple class hierarchies, as Listing 3 demonstrates:

  • Print
  • Feedback

Resources