OOP and IF Statements
It can sometimes be useful to think about what existing concept OOP replaces. References remove arithmetic operations from pointers, structured programming removes unstructured flow control (GOTO statements) from flow control, and OOP removes selection statements such as if, switch, and match that interfere with higher-level modularization. (Written sometime between 2005 and 2007)
References and Pointer Arithmetic
Pointers in the C language are a raw means of addressing that permit arithmetic operations. References in Java or C# gain advantages such as security, convenience, and GC efficiency by constraining arithmetic operations on pointers.
Structured Programming and the GOTO Statement
Structured programming removes the GOTO statement from the methods of controlling a program’s flow. To generalize by borrowing Dijkstra’s expression, what matters is removing devices that damage a meaningful programmer-independent coordinate system. According to structured program theorem, even without GOTO, flow control can be expressed through a combination of the following three means:
- sequence: simply put, code composed of recursive function calls and returns being executed from top to bottom
- selection: simply put,
if,switch,match - iteration: simply put,
while,do,until,repeat,for
The GOTO statement combined with conditional statements is a raw means of flow control, and structured programming gains advantages such as comprehensibility and modularization by constraining it.
OOP and IF Statements
Some say that OOP replaces structured programming, but that is only about one-third correct. One way to think about it is that, through subtype polymorphism, OOP replaces selection among the three flow-control means of structured programming—that is, if, switch, match, and so on.
A conditional statement is, to begin with, a branching selection mechanism, and “selection” means that the code executed afterward differs depending on the value of a particular variable. In an if statement, selection is performed according to the boolean value of the condition clause, whereas in subtype polymorphism, selection is performed according to the type of the instance receiving the message.
The following is the traditional approach:
if(mediaType.equals("monitor")) {
renderToMonitor();
} else if(mediaType.equals("printer")) {
renderToPrinter();
} else {
throw new IllegalArgumentException("Unknown media: " + mediaType);
}
The following is the approach using subtype polymorphism:
abstract class Media() { void render() }
class Monitor extends Media() { void render() { /* ... */ } }
class Printer extends Media() { void render() { /* ... */ } }
// ...
media.render();
Can subtype polymorphism, and the dependency inversion that uses it, be an important enough perspective to characterize OOP? Some people argue that it can.
It doesn’t matter what language a program is written in. If its dependencies are inverted, it has an OO design.
—Robert Cecil Martin, Agile software development (book)
To elaborate so as to avoid misunderstanding, this is not a claim that object-oriented design requires removing every if. To quote Martin Fowler’s explanation:
We are not unconditionally opposed to conditional statements. In the first edition of this book (Refactoring), there was a smell called “switch statements.” In the late 1990s, sadly, polymorphism was not yet widely enough recognized, so we considered it beneficial for people to choose polymorphism instead of
switch. —Refactoring: Improving the design of existing code
Encapsulation and Information Hiding
People usually name polymorphism, encapsulation, and information hiding as the three characteristics of OOP, but can we regard polymorphism as especially more important among them?
All three are important, but since encapsulation and information hiding are concepts that already existed before OOP, polymorphism is a relatively conspicuous distinguishing feature.
Must One Remove All ifs to Be True OOP?
There are two things one could say.
- First, “true OOP” is both vague to define and not a value especially worth pursuing.
- Second, what matters is not removing every
if, but removingifstatements that hinder higher-level modularization.
The perspective that OOP uses subtype polymorphism to replace if statements that hinder higher-level modularization is one of several useful perspectives for understanding OOP.