Missing Opportunities for Polymorphism

From WikiContent

(Difference between revisions)
Jump to: navigation, search
Line 1: Line 1:
-
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. This side by side implementation is demonstrated in listing 1.
+
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 <code>if: aBlock else: anotherBlock message</code> to <code>true</code>, it's implementation of <code>if:else:</code> will execute <code>aBlock</code>. Sending that same message to <code>false</code> will cause <code>anotherBlock</code> to be executed.
 +
For <code>True</code>:
-
true
+
if: aBlock else: anotherBlock
-
if: aBlock else: anotherBlock
+
^aBlock execute.
-
^aBlock execute.
+
-
false
+
For <code>False</code>:
-
if: aBlock else: anotherBlock
+
-
^anotherBlock execute.
+
-
Listing 1. Smalltalk's polymorphic implementation of if:else:
+
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 have 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.
+
By unifying the API for these Booleans, we can write code such as <code>result := someBoolean if: aBlock else: anotherBlock.</code> 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 in listing 1, 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.
+
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.
-
Lets 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 (enum?), accountType. I could also capture the distinction by creating two classes, CheckingAccount and SavingsAccount. Lets 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.
+
Let's consider the case where we are modeling bank accounts. Now, we could define all accounts as just that, <code>Account</code>. We could distinguish between a checking and savings account an attribute, <code>accountType</code>, which could be an <code>enum</code>. We could also capture the distinction by creating two classes, <code>CheckingAccount</code> and <code>SavingsAccount</code>. Let's say we now implement an <code>accrueInterest()</code> 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.
+
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.
 +
 
 +
By [[Kirk Pepperdine]]
 +
 
 +
This work is licensed under a [http://creativecommons.org/licenses/by/3.0/us/ Creative Commons Attribution 3]
 +
 
 +
 
 +
 
 +
Back to [[97 Things Every Programmer Should Know]] home page

Revision as of 00:41, 17 December 2008

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.

For True:

if: aBlock else: anotherBlock
    ^aBlock execute.

For False:

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, CheckingAccount and 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.

By Kirk Pepperdine

This work is licensed under a Creative Commons Attribution 3


Back to 97 Things Every Programmer Should Know home page

Personal tools