I have a module and a class.
module Dog
def speak
"woof"
end
end
class Daschund; end
I create two separate instances of the class.
sausage = Daschund.new
saveloy = Daschund.new
If I want to add Dog#woof
as an instance method of my two new objects, I can do it in two ways:
class << sausage
include Dog
end
> sausage.speak
=> "woof"
saveloy.extend Dog
> saveloy.speak
=> "woof"
Are the two methods equivalent? I know the first adds the module's method to the object's meta-class. Does object#extend
do the same thing? Or is it doing something slightly different? Is there any way to prove this?
CodePudding user response:
According to the docs for Object, extending an object with a module means including that module to the object's singleton class:
extend
: Includes the given modules in the singleton class ofself
.
Inspecting the ancestors
of both objects' singleton classes confirms this:
sausage.singleton_class.ancestors
#=> [#<Class:#<Daschund:0x00007fa6af92e868>>, Dog, Daschund, Object, Kernel, BasicObject]
saveloy.singleton_class.ancestors
#=> [#<Class:#<Daschund:0x00007fa6af92e778>>, Dog, Daschund, Object, Kernel, BasicObject]
The actual implementation details of course depend on the Ruby implementation and version you are using. For MRI/YARV, you have rb_extend_object
defined as:
void
rb_extend_object(VALUE obj, VALUE module)
{
rb_include_module(rb_singleton_class(obj), module);
}