Missing Opportunities for Polymorphism
It is not without irony that one of the best examples of polymorphism is also a sign that you are missing opportunities to exploit polymorphism. The example is best expressed in Smalltalk where the if-then-else control structure is implemented as method call. If you send an
if: aBlock else: anotherBlock message to
true, it's implementation of
if:else: will execute
aBlock. Sending that same message to
false will cause
anotherBlock to be executed.
if: aBlock else: anotherBlock ^aBlock execute.
if: aBlock else: anotherBlock ^anotherBlock execute.
By unifying the API for these Booleans, we can write code such as
result := someBoolean if: aBlock else: anotherBlock. and end up with the expected results. However, the fact that we had to execute and if-then-else in the first place was because at some point in the past we lost or did not properly captured some vital piece of information. Now that this bit of information is missing, we have to recreate that information and the tool that is most commonly used to do that is if-then-else.
How does this relate to polymorphism? One of the beautiful features of capturing state and behavior into an object is that these objects act as mini execution contexts. If we revisit the code above, we can see that we don't have to make any decisions. We can use the fact that our execution context is either true or false allows us to get straight to the block that is to executed. If we didn't completely understand the context in which we were working in, we'd be forced to some how rebuild that context in order for us to know what to do.
Let's consider the case where we are modeling bank accounts. Now, we could define all accounts as just that,
Account. We could distinguish between a checking and savings account an attribute,
accountType, which could be an
enum. We could also capture the distinction by creating two classes,
SavingsAccount. Let's say we now implement an
accrueInterest() method where each type of account has a different interest rate. With the former case we will have to write some logic to match the type of account with the rate of interest. With the later, each object knows what it is and hence can just directly acquire the interest rate. If can do this because of how it is defined without using if-then-else to rebuild that information.
Classes designed to exploit polymorphism have a much reduced dependency on if-then-else. They also tend to be more readable and contain less code. Each of these attributes show that improved polymorphism is more than just a neat coding trick, it's a technique that leads to better code.
This work is licensed under a Creative Commons Attribution 3
Back to 97 Things Every Programmer Should Know home page