In this answer, the user gave a very clear example on how classes and methods work together.
I will reprint the example here:
(defclass human () ())
(defclass dog () ())
(defmethod greet ((thing human))
(print "Hi human!"))
(defmethod greet ((thing dog))
(print "Wolf-wolf dog!"))
(defparameter Anna (make-instance 'human))
(defparameter Rex (make-instance 'dog))
(greet Anna) ;; => "Hi human"
(greet Rex) ;; => "Wolf-wolf dog!"
My question is, using the same example:
- What value would creating a generic functions add?
- Why are generic functions useful? Are they like instances in other OO languages that provide structure?
It seems that generic functions are created in the background implicitly (not 100% sure). I notice that when I play with this example, if I create a method that has a different param structure than the first instance of the method, I get a generic function error.
I like to declare the generic function explicitly because it is possible to add documentation and declarations that are relative to the generic function (optimize for speed/space/debug), and other details such as method combination (a.k.a. when you have multiple methods applicable for a given call, this defines which are executed and in which order). Here for example I can define
talkas having aprognmethod combination (all methods are executed as-if encapsulated in aprognform):This is a bit contrived example, but here we go:
Defining a class that inherits from both means that a call to
talkfor an instance of the class can execute two methods (sorted in a somewhat topological order called the Method Resolution Order). So with this method combination all the methods are executed:But, I would say that being able to document the generic function is by itself a good enough reason to declare it with
defgeneric.If you define
talkas a generic function you allow any class to participate in code that callstalk(e.g. a library), this is a way to allow extensions without having to close the set of possible values, unlike using something liketypecasein a function where you can only list a predefined set of cases.For example the standard functions
print-objectis called at various times in your Lisp implementation (in the inspector, the REPL, the debugger), if you want you can implement a method for your custom types without having to hack the internals of your environment.Generic functions are, unlike in other OO languages, not tied to a single class or instance. They can be specialized1 on more than one argument, which means none of them "owns" the generic function.
1. specialized is defined as follows:
The idea behind this is that methods can be more or less specific: a method of two arguments
aandbthat specializes both on(a number)and(b string)is more specific than another one that specializes only on(b vector), and methods are actually sorted from the most specific to the least specific ones (resp. from the least to the most) when combining them. You can even specialize a function on(a (eql 10))to cover only the specific case of an argumentabeingeqlto 10.