I got 99 problems but OOP ain’t one

Introduction

Polymorphism is the ability to change the behaviour of your code during runtime. It let’s you invoke derived methods through a base class reference. A subclass can behave differently even if it shares the same functionalities of it’s parent class. Typically this is done by using an interface or an abstract class and implementing specific classes from them. An example would be

[pastacode lang=”java” manual=”public%20class%20Preferences%20%7B%0A%0A%09…%0A%0A%09private%20Persister%20persister%20%3D%20new%20FilePersister()%3B%0A%0A%09…%0A%0A%7D” message=”” highlight=”” provider=”manual”/]

The Persister actually is an interface and the FilePersister is an implementation of this interface. If you read my last article they might seem familiar. A quick reminder:

[pastacode lang=”java” manual=”public%20interface%20Persister%20%7B%0A%0A%09public%20void%20persist(Object%20obj)%3B%0A%0A%09public%20Object%20load()%3B%0A%7D” message=”” highlight=”” provider=”manual”/]

[pastacode lang=”java” manual=”public%20class%20FilePersister%20implements%20Persister%20%7B%0A%0A%09private%20File%20file%20%3D%20new%20File(%22definitely%2Fnot%2Fthe%2Fpath%2Fto%2Fmy%2Fdesktop%22)%3B%0A%0A%09%40Override%0A%09public%20void%20persist(Object%20obj)%20%7B%0A%09%2F%2F%20ommited%20for%20simplicity%0A%09%7D%0A%0A%09%40Override%0A%09public%20Object%20load()%20%7B%0A%09%2F%2F%20ommited%20for%20simplicity%0A%09%7D%0A%0A%7D” message=”” highlight=”” provider=”manual”/]

As you can see the FilePersister is one specific implementation of the Persister interface. Let us now assume that you not only have to save the preferences into a file but also into a database. This is done by simply implementing another Persister.

[pastacode lang=”java” manual=”public%20class%20DatabasePersister%20implements%20Persister%7B%0A%0A%09String%20databaseIp%20%3D%20’127.0.0.1’%3B%0A%09String%20databaseName%20%3D%20’myDb’%3B%0A%09String%20databaseUser%20%3D%20’dbUser’%3B%0A%09String%20databasePass%20%3D%20’dbPass’%3B%0A%0A%09%40Override%0A%09public%20void%20persist(Object%20obj)%20%7B%0A%09%2F%2F%20ommited%20for%20simplicity%0A%09%7D%0A%0A%09%40Override%0A%09public%20Object%20load()%20%7B%0A%09%2F%2F%20ommited%20for%20simplicity%0A%09%7D%0A%0A%7D” message=”” highlight=”” provider=”manual”/]

Now, the only thing you have to change is the implementation of your Persister in your Preferences.class

[pastacode lang=”java” manual=”public%20class%20Preferences%20%7B%0A%0A%09…%0A%0A%09private%20Persister%20persister%20%3D%20new%20DatabasePersister()%3B%0A%0A%09…%0A%0A%7D” message=”” highlight=”” provider=”manual”/]

If the method persister.persist(Object obj) gets called it doesn´t matter if the object is a FilePersiter or DatabasePersister. Through it’s shared methods inherited from the interface, every subclass can be called from the outside no matter what the internal implementation looks like. The classes can even be exchanged without breaking any code.

Let us now assume you want to change the behaviour during runtime. The code for the persisting looks like this

[pastacode lang=”java” manual=”Persister%20persister%20%3D%20getPersister()%3B%0Apersister.persist(preferences)%3B” message=”” highlight=”” provider=”manual”/]

Super simple, isn’t it. No matter what Persister implementation get’s called, the code won’t break. Which persister get’s called can now be managed in the getPersister() method:

[pastacode lang=”java” manual=”private%20Persister%20getPersister()%20%7B%0A%09if(saveToDatabase())%7B%0A%09%09persister%20%3D%20new%20DatabasePersister()%3B%0A%09%7D%20else%20if(saveToFile())%20%7B%0A%09%09persister%20%3D%20new%20FilePersister()%3B%0A%09%7D%20else%20%7B%0A%09%09throw%20new%20IllegalStateException()%3B%0A%09%7D%0A%7D” message=”” highlight=”” provider=”manual”/]

The boolean methods saveToDatabase() and saveToFile() can for example return true or false depending on some settings the user sets in the User Interface.

For funs sake, let us now imagine you need to save the preferences into the database and into a File. To achieve this we define a MakroPersister which does all this for us.

 

[pastacode lang=”java” manual=”%0Apublic%20class%20MakroPersister%20implements%20Persister%7B%0A%0A%09List%20persisables%20%3D%20new%20ArrayList%3C%3E()%3B%0A%0A%09MakroPersister(List%20persisables)%7B%0A%09%09this.persisables%3Dpersisables%3B%0A%09%7D%0A%0A%09%40Override%0A%09public%20void%20persist(Object%20obj)%20%7B%0A%09fore(Persister%20persister%20%3A%20persisables)%7B%0A%09%09persiter.persist(obj)%3B%0A%09%09%7D%0A%09%7D%0A%0A%09%40Override%0A%09public%20Object%20load()%20%7B%0A%09fore(Persister%20persister%20%3A%20persisables)%7B%0A%09%09persiter.load()%3B%0A%09%09%7D%0A%09%7D%0A%0A%7D” message=”” highlight=”” provider=”manual”/]

This MakroPersister takes a list of Persister objects, iterates through them and calls the persist() and load() methods of every element. We can rewrite our Preferences.class like this

[pastacode lang=”java” manual=”public%20class%20Preferences%20%7B%0A%0A…%0AList%20persistables%20%3D%20new%20ArrayList%3C%3E()%3B%0Apersistables.add(new%20FilePersister())%3B%0Apersistables.add(new%20DatabasePersister())%3B%0A%0Aprivate%20Persister%20persister%20%3D%20new%20MakroPersister(persistables)%3B%0A%0A…%0A%0A%7D” message=”” highlight=”” provider=”manual”/]

If the persister.persist() method get’s called, the preferences will be stored into the file and the database. Polymorphism at it’s best, ladies and gentlemen.

What have we learned?

Polymorphism is a mighty tool to change the internal behaviour of classes without changing it’s outer functionality. We saw that we could easily change the way where our preferences got stored only by changing one single line of code. In addition we build a MakroPersister which lets us save into multiple outputs and called it the same way we called the other Persister implementations. We changed the internal behaviour without breaking the outer functionality.

Categories: Blog Posts