我只是在了解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!"
所有其他的答案都很好,包括挖掘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被扩展(复制)到包含类中。
当您将模块包含到类中时,模块方法将作为实例方法导入。
但是,当您将模块扩展为类时,模块方法将作为类方法导入。
例如,如果我们有一个模块Module_test,定义如下:
module Module_test
def func
puts "M - in module"
end
end
现在,对于include模块。如果我们这样定义A类:
class A
include Module_test
end
a = A.new
a.func
输出将是:M - in模块。
如果我们将include Module_test替换为extend Module_test并再次运行代码,我们会收到以下错误:undefined method 'func' for #<A:instance_num> (NoMethodError)。
将方法调用a.func更改为a.func,输出更改为:M - in模块。
从上面的代码执行可以清楚地看出,当我们包含一个模块时,它的方法就变成了实例方法,而当我们扩展一个模块时,它的方法就变成了类方法。