How coding to Interface and Inheritance helped me reuse code

Before going into the details I will state the requirement:

  • I need to fetch certain records from 3 different tables into 3 ArrayLists.
  • I have 3 Classes which store the information: Lets name it- Class1, Class2, Class3.
  • All the above 3 classes implement the Interface, lets name it Interface1. The interface has a method called init(). The main task of init() is to initiate the values of the instance variables with the values obtained from the ResultSet (database). This instance is then added to one of the 3 lists define above depending on the type of the reference.

Depicting in code:

public interface Interface1
{
    public void init(ResultSet rs);
}
public class Class1 implements Interface1
{
    private int m_instanceVar1;
    private String m_instanceVar2;
    public void init(ResultSet rs)
    {
        m_instanceVar1=rs.getInt(1);
        m_instanceVar2=rs.getString(2);
    }
}
public class Class2 implements Interface1
{
    private int m_instanceVar1;
    private String m_instanceVar2;
    private String m_instanceVar2;
    public void init(ResultSet rs)
    {
        m_instanceVar1=rs.getInt(1);
        m_instanceVar2=rs.getString(2);
        m_instanceVar3=rs.getString(3);
    }
}
public class Class3 implements Interface1
{
    private int m_instanceVar1;
    private String m_instanceVar2;
    private String m_instanceVar3;
    private int m_instanceVar4;
    public void init(ResultSet rs)
   {
        m_instanceVar1=rs.getInt(1);
        m_instanceVar2=rs.getString(2);
        m_instanceVar3=rs.getString(3);
        m_instanceVar4=rs.getInt(4);
   }
}

I had to use these classes in obtaining the data from the database by using some CallableStatement and then registering the out parameters to later obtain the result sets for different tables values being returned. So we have


ResultSet rsClass1;

ResultSet rsClass2;

ResultSet rsClass3;

Also there are 3 lists that are going to store the data obtained from the above result sets.


List<Class1> class1List = new ArrayList<Class1>();

List<Class1> class2List = new ArrayList<Class2>();

List<Class1> class3List = new ArrayList<Class3>();

Now I had to traverse through the result sets updating the above created list. So I did this each time for each class. Something like below:


if(rsClass1!=null)

{
    while(rs.next())
    {
        Class1 tempClass = new Class1();
        tempClass.init(rs);
        class1List.add(tempClass);
    }
}

if(rsClass2!=null)
{
    while(rsClass2.next())
    {
        Class2 tempClass = new Class2();
        tempClass.init(rsClass2);
        class2List.add(tempClass);
    }
}

if(rsClass3!=null)
{
    while(rsClass3.next())
    {
        Class3 tempClass = new Class3();
        tempClass.init(rsClass3);
        class3List.add(tempClass);
    }
}

You can see that there’s repitition of the same action- Looping through the result set, creating an instance and than adding it to the list. Looking at this the immediate response of my team member was- Where are u making use of the interface? Am not making use of coding to an Interface. The above approach could be minimized to:

public void populateListWithRS(ResultSet rs, Class<? extends Interface1> myClass, List<? extends Interface1> myList)
throws <list of exceptions>
{
    if(rs!=null)
    {
        while(rs.next())
        {
            Interface1 myInstance = myClasss.newInstance();
            myInstance.init(rs);
            myList.add(myInstance);
        }
    }
}

So now we have moved all the repeated code into a method.

 Class<? extends Interface1>

Tells that accept the Class which implement Interface1. Note that you dont use implements for Generics. Even if its an Interface we use the keyword “extends”. Similar goes with the declaration:

List<? extends Interface1> myList

Now I had to just call populateListWithRS passing appropriate parameters.


populateListWithRS(rsClass1, Class1.class, class1List);

populateListWithRS(rsClass2,Class2.class, class2List);

popualteListWithRS(rsClass3,Class3.class,class3List);

This way the verbosity and the noise of the code was reduced to a great extent. You might be wondering how could the right init() method be called for instances of different Class types- all extending/implementing same Class/Interface. What happens in Overridden methods is that- The actual method to be called is decided during run time- So if the sub class has overridden the method than the subclass’s version is called provided the instance is of the subclass’s type. It doesnt matter if the reference to this instance is of type Superclass. But this is not applicable to Static methods cause there- Hiding happens and the overridden methods are hidden if the reference is Super class type.

5 thoughts on “How coding to Interface and Inheritance helped me reuse code”

  1. Is there any article to explain or demonstrate the need for an inner class? Something other than whats in Head First Java (which I am reading already) would help.

    Reply

Leave a Reply

Discover more from Experiences Unlimited

Subscribe now to keep reading and get access to the full archive.

Continue reading