Robert K. wrote:
On 03/21/2010 06:14 PM, James Edward G. II wrote:
Not really sure about it, but…
It worked great and felt very natural to me when using it.
James, what’s the advantage of this over simply using “include”? If all
instances get to use the plugin module then you can as well include it
in the class.
As JEGII stated, the main reason to do so is related to the inheritance
chain order. If you want to be able to redefine an instance method while
keeping access to the original implementation, extend is necessary.
include will make the redefinition available but as it’s mixed-in, the
original definition trumps the redef. With extend, the order is reversed
(the original class is kind of subclassed by the module extend receives
as an argument).
This is terrific behavior for callbacks and plugins. It’s a easy as pie
to do with classes, and a little bit more tortuous to achieve for class
I see it like this: if all instances of a class should be extended with
plugin behavior, then simply use “include”. If only some instances
should, then use “extend”.
I think there’s some confusion about what extend and include really are.
We often read extend is to make module methods available as class
methods while include makes them instance methods, but that’s not true.
extend is a method of the Object class, and it can handle any object as
a receiver, be it a class, an instance of a class, or a module, a
singleton, etc. If you extend a class, then you’ll get class methods. An
instance, instance methods. And what’s so great about extend is, once
again, the way it alters the inheritance chain: the class calling extend
for a module gets subclassed by the module-now-a-class. Which means at
least two things: if you redefine the module passed to extend, then the
changes are not propagated, it’s made available only for new extending
objects; if you had a method on the object which is redefined into the
extended module, then the module-now-a-class version is the first match,
and you can call super to reach the original (class) definition.
Quite different is include, a keyword not a method, which has only one
behavior: quoting the Pickaxe, “it makes a reference from the class to
the included module. If multiple classes include that module, they’ll
all point to the same thing”. So you get shared, instance methods. The
mixed-in module is appended right next to the class including it within
the inheritance chain, so that if you call an instance method of the
class, even if it’s been redefined by the mixed-in module, the first
match’s still the class’.
So, the real difference between extend and include, aside from their
nature, is not really about whether they’re talking to classes or
instances, it’s more about their behavior: extend is useful for
redefining things (once), include (mixin) is useful for adding (shared)
things. I mean, following Yehuda K.
you can either stick to the implementation, or, you can consider the
semantic/purpose, the latter being more accurate and useful at the same