Polymorphism

  • A variable of a supertype can refer to a subtype object.

Polymorphism in Java has two types:

  • Compile time polymorphism (static binding)
  • Runtime polymorphism (dynamic binding)

##Compile time polymorphism (static binding)

  • When type of the object is determined at compile time, It is Compile time polymorphism (static binding).

If there is any private, final or static method in a class, there is static binding.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class DemoOverload{
public int add(int x, int y){ //method 1
return x+y;
}

public int add(int x, int y, int z){ //method 2
return x+y+z;
}

public int add(double x, int y){ //method 3
return (int)x+y;
}

public int add(int x, double y){ //method 4
return x+(int)y;
}
}

class Test{
public static void main(String[] args){
DemoOverload demo=new DemoOverload();
System.out.println(demo.add(2,3)); //method 1 called
System.out.println(demo.add(2,3,4)); //method 2 called
System.out.println(demo.add(2,3.4)); //method 4 called
System.out.println(demo.add(2.5,3)); //method 3 called
}
}

Runtime polymorphism (dynamic binding)

  • When type of the object is determined at runtime, it is Runtime polymorphism (dynamic binding).

If we call the overridden method on the superclass reference then the subclass version of the method will be called.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public class PolymorphismDemo {

public static void main(String[] args){
m(new GraduateStudent());
m(new Student());
m(new Person());
m(new Object());
}

public static void m(Object x) {
System.out.println(x.toString());
}
}

class GraduateStudent extends Student {
//nothing here
/*
GraduateStudent does not have a toString method
Therefore when calling m(new GraduateStudent()),
It gets the superclass's method in runtime.
*/
}

class Student extends Person {
public String toString() {
return "Student";
}
}

class Person extends Object {
public String toString() {
return "Person";
}
}

Output

1
2
3
4
Student
Student
Person
java.lang.Object@293e75df

Which implementation is used will be determined dynamically by the Java Virtual Machine (JVM) at runtime.

This capability is known as dynamic binding.

Another example of Runtime polymorphism (dynamic binding)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class A {
public void p() {
System.out.print("A");
}
}
class B extends A {
public void p() {
System.out.print("B");
}
}

public class Test {
public static void main(String args[]) {
A a = new B(); //Type is A but point to B
a.p(); //Invoke void p() of B (overrided)
B b = new B(); //Type is B, point to B
b.p(); //Invoke void p() of B
}
}

//Output: BB

Note if the Methods are static, they will not get overrided.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class A {
static void p() {
System.out.print("A");
}
}
class B extends A {
static void p() {
System.out.print("B");
}
}

public class Test {
public static void main(String args[]) {
A a = new B(); //Type is A but point to B
a.p(); //Invoke void p() of A because Static
B b = new B(); //Type is B, point to B
b.p(); //Invoke Static void p() of B
}
}

//Output: AB

Recall: when calling static method, we can call the method without new an object.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class A {
static void p() {
System.out.print("A");
}
}
class B extends A {
static void p() {
System.out.print("B");
}
}

public class Test {
public static void main(String args[]) {
A.p();
B.p();
}
}

//Output: AB

Another Example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
class A {
public A(int i) {
System.out.println(myMethod(i));
System.out.println("A1");
}
int myMethod(int i) {
System.out.println("A2");
return i;
}
}

class B extends A {
public B(int i, int j) {
super(10);
System.out.println("B1");
}
int myMethod(int i) {
System.out.println("B2");
return i;
}
}

public class Test {
public static void main(String args[]) {
B b = new B(1,2)
}
}

//Output:
// B2
// 10
// A1
// B1

Member variables have static binding

In Java, member variables have static binding because Java does not allow for polymorphic behavior with member variables.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class A {
int i = 10;
}
class B extends A {
int i = 20;
}
class C extends B {
int i = 30;
}

public class Test {
public static void main(String args[]) {
A a = new C();
System.out.print(a.i + " ");
C c = new C();
System.out.print(c.i + " ");
B b = new B();
System.out.print(b.i);
}
}

//Output: 10 30 20

Implicit Conversion

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class Person{

void p(double n){
System.out.println("A");
System.out.println(n);
}
}

class Teacher extends Person{
void p(int d){
System.out.println("B");
System.out.println(d);
}

void p(double n){
System.out.println("B2");
System.out.println(n);
}
}

class Test{
public static void main(String[] args){
//Person aa = new Person();
//Teacher aa = new Person(); //error: incompatible types: Person cannot be converted to Teacher
Person aa = new Teacher();
//Teacher aa = new Teacher();
aa.p(44);
}
}

Output is:

B2

44.0

Let’s see another example.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class A {
void p(double n) {
System.out.println("A");
System.out.println(n);
}
}
class B extends A {
void p(int d) {
System.out.println("B");
System.out.println(d);
}
void p(String c) {
System.out.println(c);
}
}

public class Test {
public static void main(String args[]) {
A aa = new A();
B bb = new B();
aa.p(123.2);
bb.p(456.7);
aa = new B();
bb = new B();
aa.p("Cat1"); //Error incompatible types: String cannot be converted to double
aa.p(44); // A 44.0
bb.p("Cat2"); // Cat2
bb.p(55); // B 55
}

}

Inheritance vs Polymorphism

  • Inheritance is implemented on the classes
  • Polymorphism is implemented on methods/functions.

Accessibility Summary

Modifier on members in a class Accessed from the same class Accessed from the same package Accessed from a subclass Accessed from a different package
public Yes Yes Yes Yes
protected Yes Yes Yes No
default Yes Yes No No
private Yes No No No

A Subclass Cannot Weaken the Accessibility

  • A subclass may override a protected method in its superclass and change its visibility to public.
  • However, a subclass cannot weaken the accessibility of a method defined in the superclass.

For example, if a method is defined as public in the superclass, it must be defined as public in the subclass.

final Class Modifier

  • The final class cannot be extended
  • The final method cannot be overridden by its subclasses
  • The final variable is a constant

Reference

Static Binding and Dynamic Binding

Quick Guide to Polymorphism in Java