The first time I discovered generic functions was while playing with Common Lisp's Object System (CLOS).
In fact, early Lisp systems worked as Smalltalk did, by implementing a send function:
instead of just doing:
They finally came with the solution of creating generic functions that could be implemented by methods. This design is far more expressive that the classic OO design, implemented in languages such as Java.
Since this design is far from classical OO ones, explaining by example turns out to be quite difficult: the wikipedia examples aren't very enlightening (see the article's discussions).
So here I go.
Java has function overloading: that means that several methods with the same name can be defined in the same class, provided that the type (or number of arguments) defined in each method is not the same.
So, for example, lets define a Java class Person with two eat methods:
This code will answer "mmm...". But there's one important thing: we've called a method from John's class, instead of some eat method from Person.
This had to be decided at run time, since me is of type Person, but we assigned a John to it...
Now lets define, in pseudo-code, an abstraction of these eat methods, that could be thought as decoupled from the John and Person classes. For example, we could re-write John and Personeat methods as four independent functions:
What we know about these methods is that Java checks its first argument type at runtime, but all other arguments are checked at compile-time.
So, as far as dynamic dispatch concerns, Java has single dispatch, and function overloading only refers to compile-time checked types, which in general doesn't yield the expected result. (This problem beeing solved by the visitor pattern in most cases).
A generic function can be seen as a family of functions that provide multiple dispatch, that means that all arguments of the function are checked at runtime (on invocation). Not only the first argument, but all.
Compared to Java, this approach would, in most cases, yield the expected answers without having to implement some patterns like the visitor pattern.
The four methods defined above could be redefined in CLOS as:
Since a generic function defines a family of functions, there's no function body in it.
A generic function can also be defined with type annotations:
A method is then defined over an existing generic function, using specializers: