In Geek roots, "poly" means many like polygon, and "morph" means forms or the way something behaves. In programming, polymorphism is the ability to change the behavior of an object as if it was another object.

In Java, Polymorphism enables us to process objects of the same superclass as if they are objects of the superclass. Subclasses of the superclass can define their own unique behaviors and yet share some of the same functionality of the superclass.

To demonstrate polymorphic features in the Java language, let us create an Animal class having a talk method and extend it with a Cat and a Dog class. For Animal, the talk method simply throws an exception, which indicates the method has not yet implemented. For Cat, override the talk method to return "Meow!". For Dog, override the method to return Woof!.

Animal Class : Superclass

class Animal {

String talk() {
   throw new UnsupportedOperationException("Animal has not implement talk");
 }
}

Cat Class extending Animal Class

class Cat extends Animal {

String talk() {
 return "Meow!";
 }
}

Dog Class extending Animal Class

class Dog extends Animal {

String talk() {
  return "Woof!";
 }
}

As Cat is a subclass of Animal, Java allows an object of type Animal to point to an object of type Cat. Hence, it is possible to write:

Animal c = new Cat();

Now the object c is capable of calling every method in Animal class. But when you call c.talk(), the actual method being applied is that of the Cat class. So, c.talk() will return the string "Meow!". The following snippet demonstrates it.

public class AnimalTest {

public static void main(String[] args) {

Animal[] pets = new Animal[3];
pets[0] = new Cat();
pets[1] = new Dog();
pets[2] = new Animal();
for (int i = 0; i < pets.length; i++) {
System.out.println("Pet[" + i + "]: " + pets[i].talk());
   }
  }
}

The above code produce:

Pet[0]: Meow!

Pet[1]: Woof!

Exception in thread "main" java.lang.UnsupportedOperationException: Animal has not implement talk

at Animal.talk(AnimalTest.java:11)

at AnimalTest.main(AnimalTest.java:35)

The talk method of Pet[2] is of Animal class. The method intentionally throws an exception as it is not implemented.

Abstract Class

Sometimes, we want a superclass to just act as a general pattern. Based on the pattern, an object of the superclass becomes a type to exploit the polymorphic feature of Java language similar to the array of Animal mentioned above. However, we have no intention to allow an Animal in general to talk, thus the program throws an exception when the method is called. All this happens at run time, so we must run our program and hope to discover the mistake as soon as possible. There is a better way, though. By stating that Animal is an abstract class, there will be no object of such class, thus no call to the should-not-exist talk method.

abstract class Animal {

   abstract String talk();

 }

Note : Using the new Animal class, the compiler complains about creating an object of abstract Animal class.

error: Animal is abstract; cannot be instantiated

pets[2] = new Animal();

Furthermore, extending an abstract class without implementing all of its abstract methods results in a compile-time error. For example, we create a non-abstract Fish class using Animal as its superclass but forget to implement the talk method.

class Fish extends Animal {

}

The compile-time error looks like

error: Fish is not abstract and does not override abstract method talk() in Animal class

Interface

There are a number of situations where it is important to have a group of classes to exhibit a common behavior. For example, we want a Radio class to have the talk method as the Cat class has. Surely, a Radio should not be classified as an Animal, yet need to be called via a talk interface.

In Java, an interface type is similar to an abstract class. Specifically, acting as a template, it could not do anything. The implements keyword is used to state that the following class implements all the methods specified in the interface.

Here is an example.

// File TalkInterfaceTest.java
import java.io.*; // header stuff MUST go above the first class

interface Talk {
	String talk();
}

class Cat implements Talk {
    public String talk() {
        return "Meow!";
    }
}

class Radio implements Talk {
    public String talk() {
        return "This is the Voice of America!";
    }
}

public class TalkInterfaceTest {

    public static void main(String[] args) {
        Talk[] things = new Talk[2];
      	Cat c = new Cat();
      	Radio r = new Radio();
        things[0] = c;
        things[1] = r;
        for (int i = 0; i < things.length; i++) {
            System.out.println("Things[" + i + "]: " + things[i].talk());
        }
    }
}

In the above code, the Talk interface is used to references objects in the things array. Such objects can invoke only methods specified in the interface.

Try it, you will see the following output

Things[0]: Meow!

Things[1]: This is the Voice of America!

At this point, you may be asking "What is the difference between abstract and interface?" There are many differences. Notably, a class can implement multiple interfaces but inherit no more than one class. An abstract class can have non-static members and methods to access those members, but an interface is a mere composition of method declarations.

In practice, interface are used quite often but abstract is not. A lot of objects have the same interface, but only a small number of them are organized into a hierarchy. The reason to favor which one is out of the scope of this article. For those new to the OOP concept, practical experience is more useful than the minute differences in concept between abstract and interface.

Summary

  • Polymorphism enables us to process objects of the same superclass as if they are objects of the superclass. Although being invoked under the same method name, how objects of the subclasses behave depends on the subclasses themselves.
  • An abstract class provides an appropriate superclass from which other classes can inherit and thus share a common design.
  • An interface provides a common behavior that all classes implementing it has to provide.
Inheritance
Inheritance
Previous Article
Exception Handling
Exception Handling
Next Article
Lakshay Sharma
I’M LAKSHAY SHARMA AND I’M A FULL-STACK TEST AUTOMATION ENGINEER. Have passed 16 years playing with automation in mammoth projects like O2 (UK), Sprint (US), TD Bank (CA), Canadian Tire (CA), NHS (UK) & ASOS(UK). Currently, I am working with RABO Bank as a Chapter Lead QA. I am passionate about designing Automation Frameworks that follow OOPS concepts and Design patterns.
Reviewers
Virender Singh's Photo
Virender Singh

Similar Articles

Feedback