From: Sean O'Halpin Date: 2012-07-16T06:29:17+09:00 Subject: Re: included() vs extended() On Mon, Sep 1, 2008 at 4:58 PM, James Coglan wrote: > So my question is: given that extend() is implemented (I think) using > metclass.include(), and that the end result of both is identical, how come > Hooks.included is not called when using extend()? It seems reasonable that > both the included() and extended() hooks should be called in this situation, > though I can just as well see the argument against doing this. Anyone care > to enlighten/persuade me as to why this behaviour exists? > In 1.9.3 at least, Object#extend calls rb_mod_extend_object() which just calls rb_extend_object() which is implemented as: void rb_extend_object(VALUE obj, VALUE module) { rb_include_module(rb_singleton_class(obj), module); } which bears out your hunch about the low-level implementation. However, Object#extend and Module#include differ in that they call different sets of hooks - #extend calls #extend_object and #extended where #include calls #append_features and #included. I guess #extend does not trigger a call to #included because it enables you to distinguish the different use cases for a module (being included into a class and extending a specific object). You've shown that you can reproduce the effect of #extend by using #include directly on a singleton class but by including a module directly into a class's singleton class you're going 'under the hood' as it were (and note that you have to use #send(:include, Hooks) here where you could have just used Bar.extend(Hooks) instead). Given the different intended use cases for #include and #extend, it does not strike me as anomalous that #extend does not trigger a call to #included. Regards, Sean