我只是在了解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实际上是append_features的别名,它(来自文档):

Ruby的默认实现是to 添加常量、方法和模块 将该模块的变量转换为aModule if 此模块尚未添加 阿莫杜勒或它的祖先之一

其他回答

我看到了一篇非常有用的文章,比较了类中使用的include、extend和prepend方法:

Include将模块方法作为实例方法添加到类中,而extend将模块方法作为类方法添加。要包含或扩展的模块必须相应定义

这是正确的。

在幕后,include实际上是append_features的别名,它(来自文档):

Ruby的默认实现是to 添加常量、方法和模块 将该模块的变量转换为aModule if 此模块尚未添加 阿莫杜勒或它的祖先之一

所有其他的答案都很好,包括挖掘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模块。

从上面的代码执行可以清楚地看出,当我们包含一个模块时,它的方法就变成了实例方法,而当我们扩展一个模块时,它的方法就变成了类方法。

你说得对。然而,事情远不止如此。

如果你有一个类Klazz和模块Mod,在Klazz中包含Mod可以让Klazz的实例访问Mod的方法。或者你可以用Mod扩展Klazz,让类Klazz可以访问Mod的方法。但是你也可以用o.extend Mod扩展任意对象。在这种情况下,单个对象获得Mod的方法,而与o具有相同类的所有其他对象都没有。