What is the difference between include and extend in Ruby?
Just getting my head around Ruby metaprogramming. The mixin/modules always manage to confuse me.
So is the major difference just this or is a bigger dragon lurking? eg
module ReusableModule
def module_method
puts "Module Method: Hi there!"
end
end
class ClassThatIncludes
include ReusableModule
end
class ClassThatExtends
extend ReusableModule
end
puts "Include"
ClassThatIncludes.new.module_method # "Module Method: Hi there!"
puts "Extend"
ClassThatExtends.module_method # "Module Method: Hi there!"
What you have said is correct. However there is more to it than that.
If you have a class Klazz
and module Mod
, including Mod
in Klazz
gives instances of Klazz
access to Mod
's methods. Or you can extend Klazz
with Mod
giving the class Klazz
access to Mod
's methods. But also you can extend an arbitrary object with o.extend Mod
. In this case the individual object gets Mod
's methods even though all other objects with the same class as o
do not.
extend - adds the specified module's methods and constants to the target's metaclass (ie the singleton class) eg
Klazz.extend(Mod)
, now Klazz has Mod's methods (as class methods) obj.extend(Mod)
, now obj has Mod's methods (as instance methods), but no other instance of of obj.class
has those methods added. extend
is a public method include - By default, it mixes in the specified module's methods as instance methods in the target module/class. eg
class Klazz; include Mod; end;
class Klazz; include Mod; end;
, now all instances of Klazz have access to Mod's methods (as instance methods) include
is a private method, because it's intended to be called from within the container class/module. However , modules very often override include
's behavior by monkey-patching the included
method. This is very prominent in legacy Rails code. more details from Yehuda Katz.
Further details about include
, with its default behavior, assuming you've run the following code
class Klazz
include Mod
end
@@foo
or @@bar
super
in Klazz#foo will check for Mod#foo before checking to Klazz's real superclass's foo method. See the RubySpec for details.). Of course, the ruby core documentation is always the best place to go for these things. The RubySpec project was also a fantastic resource, because they documented the functionality precisely.
#include
RubySpec rubydoc #included
RubySpec rubydoc #extend
RubySpec rubydoc #extended
RubySpec rubydoc #extend_object
RubySpec rubydoc #append_features
RubySpec rubydoc That's correct.
Behind the scenes, include is actually an alias for append_features , which (from the docs):
Ruby's default implementation is to add the constants, methods, and module variables of this module to aModule if this module has not already been added to aModule or one of its ancestors.
链接地址: http://www.djcxy.com/p/80896.html上一篇: 在递归函数中停止settimeout
下一篇: 在Ruby中包含和扩展有什么区别?