Today's Question:  What does your personal desk look like?        GIVE A SHOUT

Java Polymorphism and Overriding Methods

  Peter Chng        2011-10-04 14:09:06       2,730        0    

Most Java developers will be familiar with polymorphism – we’ve all seen the example of the Dog and Cat classes inheriting from some abstract Animal class and having their say() methods produce different results. But it’s still worthwhile to look at a few simple examples to reinforce the concepts.

First, we define a simple class with one instance method and one static method.

public class A
{
  public String getName()
  {
    return "I am A";
  }

  public static String getStaticName()
  {
    return "Statically A!";
  }
}

Then we extend that class with one that has identical method signatures.

public class B extends A
{
  // Note: @Override only makes sense for instance methods.
  // The annotation is not needed but makes for best practices, since if the
  // method DOES NOT override a superclass, a compile-time error will be
  // generated, limiting damage. (@Override was added in Java 1.5)
  @Override
  public String getName()
  {
    return "I am B";
  }

  public String onlyOnB()
  {
    return "Only available on B";
  }

  // Cannot @Override, generates a compile error. Instead, this methods
  // `hides` the one in the super class.
  public static String getStaticName()
  {
    return "Statically B!";
  }

  public static void main( String[] args )
  {
    A a = new A();
    B b = new B();

    A b_as_a = new B();
    A b_as_a_copied_from_reference = b;

    System.out.println(a.getName());
    System.out.println(a.getStaticName() + "\n");

    System.out.println(b.getName());
    System.out.println(b.getStaticName() + "\n");

    System.out.println(b_as_a.getName());
    System.out.println(b_as_a.getStaticName() + "\n");

    System.out.println(b_as_a_copied_from_reference.getName());
    System.out.println(b_as_a_copied_from_reference.getStaticName() + "\n");
  }
}

Sorry for the funky variable names in main(), but camelCase just didn’t look good. Anyway, can you guess the output of the program? It’s actually quite interesting:

I am A
Statically A!

I am B
Statically B!

I am B
Statically A!

I am B
Statically A!

The first two are fairly straightforward, since for variables a and b, the declared type matches the instantiated type, so there can be no doubt. But what happens when the declared type does not match the instantiated type, as in the second two examples?

The short answer is this: When instance methods are invoked, they will always be called on the instantiated type, regardless of the declared type. When static or class methods are invoked, they will be called on the declared type.

Declared type vs. instantiated type

You can think of the declared type as a “window” into the actual instantiated type. This “window” provides a view as to what methods are available for invocation and provides these hints to the compiler. This is why you cannot call a method that exists on an instantiated type unless it has been declared or exists on the declared type. (The use of interfaces provides the best example of this)

When an instance method is invoked, the JVM will then determine the runtimetype of the variable and then call the appropriate method on that object. This is why for the last two examples, the output was I am B, even though the declared type was A. This is what allows polymorphism to work in Java.

However, when a static or class method is invoked, it will always be invoked from the declared type, regardless of what the runtime or instance type is. This is because static methods are per-class rather than per-instance and thus the exact method invoked can be determined at compile time from the declared type. This is why for the last two examples, the output is from the the method defined on class A, the declared type of the two variables.

What Sun has to say

Sun’s own tutorials on these subjects refers to this as hiding; that is, when a subclass static method has the same signature as one in a superclass, it hidesit instead of overriding it. Override is a term reserved for instance methods only, and in fact, marking getStaticName() with the annotation @Override in class B results in a compile-time error.

However, to me, it’s far simpler to just remember that static methods are always invoked on the declared type, while instance methods will be invoked on the instantiated type. This provides an easy way to remember how things work in the JVM.

Source : http://unitstep.net/blog/2009/02/13/java-polymorphism-and-overriding-methods/

JAVA  POLYMORPHISM  DEMO  OVERRIDING  DYNAMI 

Share on Facebook  Share on Twitter  Share on Weibo  Share on Reddit 

  RELATED


  0 COMMENT


No comment for this article.