Friday 22 November 2013

Java Tip: Do not attempt to call a method in a superclass once it has been overridden

Well, it is impossible to call a method in superclass once it has been overridden in the subclass. Well, little things like these are basics of Java and OOP but it is not very unusual to forget them and see some pretty amusing results. I will illustrate the same with an example:

Consider the following classes Mock, MockSubClass and MockerMain.

As the name goes, MockSubClass inherits from the parent class Mock and MockerMain is the class bearing my main method.

The class definitions have been given below:
package mocker;

import java.util.Collection;
import java.util.Set;

MOCK
public class Mock {

Set s;

protected Mock (Set newSet) {
s = newSet;
}

protected void addMethod (Object o) {
s.add(o);
}

protected void addMethodAll (Collection c) {

System.out.println("Inside method addMethodAll\n");

for ( Object o: c ) {
addMethod (o);
}
}

protected Collection getCollection () {
return s;
}
} //end class Mock

MOCKSUBCLASS

package mocker;

import java.util.Collection;
import java.util.Set;


public class MockSubClass extends Mock{

/**
*/
int addCount;
public MockSubClass (Set c) {
// TODO Auto-generated constructor stub
super (c);
addCount = 0;
}
public void addMethod (Object o) {
System.out.println("Inside MockSubClass.addMethod\n");
addCount++;
super.addMethod(o);
}
public void addMethodAll (Collection c) {
int size = c.size();
addCount = addCount + size;
super.addMethodAll(c);
}
public int getAddCount () {
return addCount;
}
public Collection getCollection () {
return super.getCollection();
}

}//end class MockSubClass

MOCKERMAIN

package mocker;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

public class MockerMain {

/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
int count = 0;
Set <String> s = new HashSet <String> ();
MockSubClass Obj = new MockSubClass (s);
Obj.addMethod("LV");
count = Obj.getAddCount();
System.out.printf("1.)"+"count = "+count+"\n");
Obj.addMethodAll(Arrays.asList("LA","Sacramento","SF"));
count = Obj.getAddCount();
System.out.printf("2.)"+"count = "+count+"\n");
System.out.printf("3.)"+"List = "+Obj.getCollection()+"\n");
}

}//end class MockerMain

Well, what I am looking to do here is to create a collection and add some random strings to the collection and use the method getAddCount() in MockSubClass to retrieve the value of number of elements in the collection currently. I inserted one element first and then the addCount got updated accordingly in MockSubClass. Now, I am adding three more elements and the 3 is being added to the current value of addCount which is 1. Well, that's what the code appears to be doing. But, here is where we need to understand that addMethodAll in MockSubClass makes a call to addMethodAll in the superclass, Mock. On careful examination of the method, addMethodAll in Mock, we can see that it in turn makes a call to addMethod one time each for each element of the collection which is being added. The method, addMethod has been overridden by the subclass, so the call is actually serviced by the version in the subclass and not by the one in the superclass itself. This therefore leads to addition by another 3 and the value of addCount at this point is 7 and not 4 as required.

Output:
Inside MockSubClass.addMethod

1.)count = 1
Inside method addMethodAll

Inside MockSubClass.addMethod

Inside MockSubClass.addMethod

Inside MockSubClass.addMethod

2.)count = 7
3.)List = [LA, LV, SF, Sacramento]


No comments:

Post a Comment