According to Mr. Fogus in the sexy “Joy of Clojure”, the expression problem refers to the desire (hehe) to implement an existing set of abstract methods for an existing concrete class without having to change the code that defines either.
Object-oriented languages allow you to implement an existing abstract method in a concrete class you control (interface inheritance), but if the concrete class is outside your control, the options for making it implement new or existing abstract methods tend to be sparse. Some dynamic languages such as Ruby and JavaScript provide partial solutions to this problem by allowing you to add methods to an existing concrete object, a feature sometimes known as monkey-patching.
A Clojure protocol can be extended to any type where it makes sense, even those that were never anticipated by the original implementor of the type or the original designer of the protocol. We’ll dive deeper into Clojure’s flavor of polymorphism in chapter 9, but we hope now you have a basic idea of how it works.
Hm, I wonder how Clojurian protocol extension differs from Ruby monkeypatching?
SUBTYPING AND INTERFACE-ORIENTED PROGRAMMING
Clojure provides a form of subtyping by allowing the creation of ad-hoc hierarchies. We’ll delve into leveraging the ad-hoc hierarchy facility later, in section 9.2. Likewise, Clojure provides a capability similar to Java’s interfaces via its protocol mechanism. By defining a logically grouped set of functions, you can begin to define protocols to which data-type abstractions must adhere. This abstraction-oriented programming model is key in building large-scale applications, as you’ll discover in section 9.3 and beyond.