Functional Programming From an Object-Oriented Perspective
By: Randal Kamradt Sr
Tags: Java, Programming, Functional Programming, Object Oriented, Design Patterns

Functional Programming From an Object-Oriented Perspective

Why I’m slowly abandoning my object-oriented past

Image by StockSnap from Pixabay.

The C programming language could be a functional programming language (that aspect was and may still be implementation-dependent). On most host systems, if you left the parentheses off the function, it was just a pointer to a function. You could pass it in as a parameter or return it from a function and de-reference it by applying parentheses to it. The only problem is that the return type and parameters to a de-referenced function pointer were often lost in the shuffle and anybody's guess.

I learned all this while studying the source code to XLISP, which was an experimental LISP interpreter written in C. The author, David Michael Betz, took great pains to identify different types of functions and provide the necessary typing and casting to be able to use the functions and have the code be reasonably understandable.

Other users of functional programming were not so successful in wrangling their code into some semblance of readability. In many ways, C++ programming was a reaction to this free-for-all style of functional programming. If we think about how C++ implements objects, it maintains a list of function pointers for each “virtual” function and this list of function pointers can be modified by subclasses, which is how it achieves polymorphism.

But this method of determining functions at runtime is very restrictive. Only non-static methods of classes can be overridden, and they have to be overridden by subclassing. This allowed for a narrow style of programming, where we could classify things and define the ways in which their behavior diverges. It allowed for code reuse by putting common behavior in a base class that could be altered only in very specific ways by calling overridden methods.

With Java 8, things kind of went full circle. It introduced a functional style of programming using Single Abstract Method (SAM) classes. This used the function-overriding capability of the Java object-oriented architecture to make function objects.

For me, one of the biggest shortcomings of object-oriented programming is the inability to generically capture many common patterns. Take, for instance, the “Factory” pattern. There is no Factory class in the Java standard library, even though it is probably one of the most used patterns. I’ve made more Factory classes than I care to count.

Of course, a Factory object is inherently object-oriented, as it returns an object that implements an interface or extends a base class. But, at heart, it is a map of “suppliers” (a function that takes no argument but returns something). Assuming you have a Car interface and a bunch of classes that implement it, a factory should take some symbolic value and return a car of a particular type. The traditional implementation uses a switch to return a new value based on an enumeration or String value:

But this encloses all the knowledge of the types and options. To add to it, you have to add to the class itself.

If you were to do this the functional way, you wouldn’t have to give the factory knowledge of types or options:

All of the knowledge of the factory could be externalized and the factory could be extended without altering the code.

Here’s how you could use both of these factories:

So the FunctionalFactory takes a little more effort to build, but it’s also extensible without modifying the factory class. This satisfies the “Open-Close Principle” of SOLID, as it is easy to extend but doesn’t need to be modified.