Java OOP – Why Instantiate an Object to a Base Class Rather Than a Specific Subclass?

javaobject-oriented

For example:

URL blogFeedUrl = new URL("http://manishmaharzan.com.np/getJSON/json.json");
HttpURLConnection connection = (HttpURLConnection) blogFeedUrl.openConnection();
connection.connect();
InputStream inputStream = connection.getInputStream();
Reader reader = new InputStreamReader(inputStream);
int contentLength = connection.getContentLength();
char[] charArray = new char[contentLength];
reader.read(charArray);
String responseData = new String(charArray);

Here we could have created InputStreamReader instead for parent class Reader:

InputStreamReader reader = new InputStreamReader(inputStream);

Or for another example when creating a SQLiteOpenHelper in an activity:

public class Helper extends SQLiteOpenHelper
{
    …
}

public class DrinkActivity extends Activity
{
   protected void onCreate(…) { … }
   SQLiteOpenHelper helper = new Helper(this);
   …
}

Instead of referencing the base class SQLiteOpenHelper here, why not create

Helper helper = new Helper(this);

after all Helper extends SQLiteOpenHelper.

What is the benefit of coding it this way?

Best Answer

In layman's words:

By declaring the variable with the superclass type (i.e. Reader or SQLiteOpenHelper) you assure that the code that uses that object will work even if you instatiate it to a different kind of Reader or a different kind of SQLiteOpenHelper as long as they are a subclass of Reader or SQLiteOpenHelper respectively. The code should work fine if you pass it a FileReader or a StringReader.

A real life comparison:

When you learn to drive a manual transmission car, you can drive almost any manual transmission car. Imagine how bad it would be if you had to learn to drive every different model of car you encounter.

What you learned is abstract: shifting gears, using the clutch, etc. It applies to lots of car models as long as they respect that way of working. Being abstract and not depending on any particular car model, your driving skills are more useful.

That's not coincidence. Car makers design their cars to comply with what you expect. Every car is different, some have bells and wistles, but by having a clutch, a steering wheel (instead of a joystick), and by having the clutch, brake and gas pedal in the locations you expect, they leverage the fact that most users learned to drive an abstract "manual transmission car". Some cars have assisted steering, others have ABS brakes but those details are transparent to you. You don't have to know about them in order to use the general skills of how to drive.

When you write code depending on Reader, you are teaching your code tricks that are more useful. It will be able to handle any Reader. If you code for a specific implementation, like InputStreamReader, your code is less useful, because you most surely will end up calling methods that only exist in that specific implementation. If that's what you need to do, so be it, but if that's not so, by programming to the more general (abstract) class (declaring your variables as that) your code will benefit and it will be more flexible.

Related Topic