I like Common Lisp Object System (CLOS) and multimethods.
Most, if not all, object-oriented programming languages have the basic notions of classes and methods. The following snippet in Python defines the classes PeelingTool and Vegetable (something similar to the Visitor pattern):
class PeelingTool:
"""I'm used to peel things. Mostly fruit, but anything peelable goes."""
def peel(self, veggie):
veggie.get_peeled(self)
class Veggie:
"""I'm a defenseless Veggie. I obey the get_peeled protocol
used by the PeelingTool"""
def get_peeled(self, tool):
pass
class FingerTool(PeelingTool):
...
class KnifeTool(PeelingTool):
...
class Banana(Veggie):
def get_peeled(self, tool):
if type(tool) == FingerTool:
self.hold_and_peel(tool)
elif type(tool) == KnifeTool:
self.cut_in_half(tool)
You put the peel
method in the PeelingTool and have the Banana accept it. But, it must belong to the PeelingTool class, so it can only be used if you have an instance of the PeelingTool class.
The Common Lisp Object System version:
(defclass peeling-tool () ())
(defclass knife-tool (peeling-tool) ())
(defclass finger-tool (peeling-tool) ())
(defclass veggie () ())
(defclass banana (veggie) ())
(defgeneric peel (veggie tool)
(:documentation "I peel veggies, or actually anything that wants to be peeled"))
;; It might be possible to peel any object using any tool,
;; but I have no idea how. Left as an exercise for the reader
(defmethod peel (veggie tool)
...)
;; Bananas are easy to peel with our fingers!
(defmethod peel ((veggie banana) (tool finger-tool))
(with-hands (left-hand right-hand) *me*
(hold-object left-hand banana)
(peel-with-fingers right-hand tool banana)))
;; Slightly different using a knife
(defmethod peel ((veggie banana) (tool knife-tool))
(with-hands (left-hand right-hand) *me*
(hold-object left-hand banana)
(cut-in-half tool banana)))
Anything can be written in any language that's Turing complete; the difference between the languages is how many hoops you have to jump through to get the equivalent result.
A powerful languages like Common Lisp, with functionality such as macros and the CLOS, allows you to achieve results fast and easy without jumping through so many hoops that you either settle for a subpar solution, or find yourself becoming a kangaroo.