in Java, Reading Notes

TIJ chapter 8: Polymorphism

Polymorphism(also called dynamic binding or late binding or run-time binding) is an essential concept in OOP. This chapter is basically a more detailed explanation of polymorphism, which is highly relevant to inheritance. (As mentioned in chapter 7, in many cases inheritance is meaningless when polymorphism is not necessary.)

Binding method

How Java find a corresponding method for an object? Unlike languages like C, which use early binding for each function, Java only does early binding for methods with modifiers like static or final. Java has runtime binding for other methods. That’s the reason why people declare methods “final” in the early versions of Java to improve performance.

Runtime binding helps the compiler to refer to an override method to the correct derived class, even if we only know a base-class reference to an object. We can construct special cases where even programmer doesn’t know what kind of derived class an object belongs to, but finally, the compiler will figure out it during the runtime. During runtime, the compiler binds correct binary.

Dynamic dispatch is a fundamental feature of OOP. Java does this for each method, while C++ only enable it for virtual functions.

Extensibility

In this way, the behavior won’t change even if we add new methods for based classes and derived classes, or we add a new derived class. OOP provides extensibility to programming.

Pitfalls

For private methods in a base class, even if you have a public method with the same signature in a derived class, you will call the private one in the base class for a base class reference. It won’t throw an exception, so this should be noticed.

Another thing to note is dynamic binding is only for methods, not field. But if we set each field private and use getters and setters, this shouldn’t be a problem.

Constructor, Destructor, and Polymorphism

The constructor is a static method. When the constructor is called, the calling order is from base to derived. If we have to build a destructor, we will make it reverse, from derived to base.

How about calling overload method in the constructor of the base class?

class Base {
   void method(){
      System.out.println("base method");
   }
   Base(){ method(); }
}
class Derived extends Base {
   private int val = 1;
   void method(){
      System.out.println("val = " + val);
   }
   Derived(int i){
      super();
      val = i;
   }
   public static void main(String args[]){
      new Derived(5);
   }
}

When the constructor of the base class, method successfully refer to the derived one. However, the derived-related field has not been initialized. So the value printed is neither 1 nor 5. In fact, it is 0.

Memory space is initialized to 0 for objects, and that’s why we get 0 as output. To avoid this, the programmer should think twice before she/he call a method in a constructor. Only final methods (include private ones) are safe to be called in the constructor.

Downcasting

Sometimes we need to downcast an object to call methods only in derived class. Java will check if the downcasting is safe. If not, it will throw a ClassCastException.

 

 

 

Write a Comment

Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.

  • Related Content by Tag