例如,rubygem Devise 在lib/devise/controllers/helpers.rb
module Helpers
extend ActiveSupport::Concern
为什么在这里使用extend
? include
会做同样的事吗?
答案 0 :(得分:3)
不,include
不会这样做。
extend
和include
执行类似但不同的角色。 include
获取包含模块的实例方法,并使其可用于包含模块的实例。实际上,include
将包含的模块作为包含的超类插入(事实上,#ancestors
甚至会显示包含的模块。)
extend
将命名模块的方法添加到接收器。在模块定义期间调用extend
的情况下,这意味着“扩展”模块的实例方法将成为“扩展”模块的类方法。它通常用于将装饰器(实际上只是对类方法的调用)导入到正在定义的类或模块中。
因此,简而言之,上面的代码段将采用ActiveSupport::Concern
的实例方法,并使它们成为Helpers
的类方法。
答案 1 :(得分:2)
基本上,Object#extend
只是:
class Object
def extend(*ms)
ms.each do |m|
class << self
include m # Obviously, this won't work since m isn't in scope
end
end
end
end
因此,很容易看出它们显然不相同,因为这些方法最终会出现在不同的类中。
正在运作,但不太明显的Object#extend
版本将是:
class Object
def extend(*ms)
ms.each do |m|
singleton_class.send :include, m # Because Module#include is private
end
end
end