我只是在了解Ruby元编程。mixin/modules总是把我弄糊涂。
Include:在目标类中混合指定的模块方法作为实例方法
扩展:在目标类中混合指定的模块方法作为类方法
所以主要的区别是这一点,还是有更大的龙潜伏着?
如。
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!"
我还想解释一下它的工作机制。如果我说得不对,请指正。
当我们使用include时,我们是在从类中添加一个链接到包含一些方法的模块。
class A
include MyMOd
end
a = A.new
a.some_method
对象没有方法,只有类和模块有。
因此,当一个接收到消息some_method时,它开始在a的特征类中搜索方法some_method,然后在a类中搜索方法some_method,然后在链接到a类的模块中搜索方法some_method(如果有的话)(倒序,最后包含的胜出)。
当我们使用extend时,我们是在向对象的特征类中的模块添加链接。
因此,如果我们使用A.new.extend(MyMod),我们就是在给我们的模块添加到A的实例特征类或'类的链接。
如果我们使用A.extend(MyMod),我们将链接添加到A(对象的,类也是对象)特征类A'。
a的方法查找路径如下:
a' => a' =>链接模块到a' class =>
还有一个prepend方法可以改变查找路径:
a => a' =>前置模块到a => a =>包含模块到a
对不起,我的英语不好。
所有其他的答案都很好,包括挖掘RubySpecs的提示:
https://github.com/rubyspec/rubyspec/blob/master/core/module/include_spec.rb
https://github.com/rubyspec/rubyspec/blob/master/core/module/extend_object_spec.rb
至于用例:
如果在类ClassThatIncludes中包含模块ReusableModule,则会引用方法、常量、类、子模块和其他声明。
如果你用模块ReusableModule扩展类ClassThatExtends,那么方法和常量就会被复制。显然,如果不小心,动态复制定义可能会浪费大量内存。
如果你使用ActiveSupport::Concern, .included()函数可以让你直接重写include类。关注点中的模块ClassMethods被扩展(复制)到包含类中。