刚刚开始关注Ruby元编程.mixin/modules总是让我困惑.
include:将指定模块方法中的混合作为目标类中的实例方法
extend:将指定的模块方法混合为目标类中的类方法
那么主要区别在于这还是潜伏着更大的龙? 例如
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!"
John Douthat.. 310
extend - 将指定模块的方法和常量添加到目标的元类(即单例类),例如
如果你打电话Klazz.extend(Mod)
,现在Klazz有Mod的方法(作为类方法)
如果你调用obj.extend(Mod)
,现在obj有Mod的方法(作为实例方法),但没有其他实例obj.class
添加了这些方法.
extend
是一种公共方法
include - 默认情况下,它将指定模块的方法混合为目标模块/类中的实例方法.例如
如果你打电话class Klazz; include Mod; end;
,现在Klazz的所有实例都可以访问Mod的方法(作为实例方法)
include
是一个私有方法,因为它旨在从容器类/模块中调用.
但是,模块经常通过修补方法来覆盖其 include
行为included
.这在传统的Rails代码中非常突出.来自Yehuda Katz的更多细节.
include
假设您运行以下代码,有关其默认行为的更多详细信息
class Klazz include Mod end
如果Mod已包含在Klazz或其祖先之一中,则include语句无效
它还包括Mod在Klazz中的常量,只要它们不冲突
它使Klazz可以访问Mod的模块变量,例如@@foo
或@@bar
如果存在循环包含则引发ArgumentError
将模块作为调用者的直接祖先附加(即它将Mod添加到Klazz.ancestors,但是Mod没有添加到Klazz.superclass.superclass.superclass的链中.因此,调用super
Klazz #foo将在检查之前检查Mod#foo Klazz的真正超类的foo方法.有关详细信息,请参阅RubySpec.).
当然,ruby核心文档总是最适合这些事情的地方.RubySpec项目也是一个很棒的资源,因为他们精确地记录了这些功能.
#include
RubySpec rubydoc
#included
RubySpec rubydoc
#extend
RubySpec rubydoc
#extended
RubySpec rubydoc
#extend_object
RubySpec rubydoc
#append_features
RubySpec rubydoc
我知道这是一个相当古老的帖子,但回复的清晰度不能阻止我评论.非常感谢您的解释. (18认同)
domgblackwel.. 240
你所说的是对的.然而,除此之外还有更多.
如果你有一个类Klazz
和模块Mod
,包括Mod
in Klazz
给出了Klazz
访问Mod
方法的实例.或者你可以Klazz
通过Mod
赋予类 Klazz
访问Mod
方法来扩展.但是你也可以扩展一个任意对象o.extend Mod
.在这种情况下,单个对象获取Mod
方法,即使具有相同类的所有其他对象o
也没有.
extend - 将指定模块的方法和常量添加到目标的元类(即单例类),例如
如果你打电话Klazz.extend(Mod)
,现在Klazz有Mod的方法(作为类方法)
如果你调用obj.extend(Mod)
,现在obj有Mod的方法(作为实例方法),但没有其他实例obj.class
添加了这些方法.
extend
是一种公共方法
include - 默认情况下,它将指定模块的方法混合为目标模块/类中的实例方法.例如
如果你打电话class Klazz; include Mod; end;
,现在Klazz的所有实例都可以访问Mod的方法(作为实例方法)
include
是一个私有方法,因为它旨在从容器类/模块中调用.
但是,模块经常通过修补方法来覆盖其 include
行为included
.这在传统的Rails代码中非常突出.来自Yehuda Katz的更多细节.
include
假设您运行以下代码,有关其默认行为的更多详细信息
class Klazz include Mod end
如果Mod已包含在Klazz或其祖先之一中,则include语句无效
它还包括Mod在Klazz中的常量,只要它们不冲突
它使Klazz可以访问Mod的模块变量,例如@@foo
或@@bar
如果存在循环包含则引发ArgumentError
将模块作为调用者的直接祖先附加(即它将Mod添加到Klazz.ancestors,但是Mod没有添加到Klazz.superclass.superclass.superclass的链中.因此,调用super
Klazz #foo将在检查之前检查Mod#foo Klazz的真正超类的foo方法.有关详细信息,请参阅RubySpec.).
当然,ruby核心文档总是最适合这些事情的地方.RubySpec项目也是一个很棒的资源,因为他们精确地记录了这些功能.
#include
RubySpec rubydoc
#included
RubySpec rubydoc
#extend
RubySpec rubydoc
#extended
RubySpec rubydoc
#extend_object
RubySpec rubydoc
#append_features
RubySpec rubydoc
你所说的是对的.然而,除此之外还有更多.
如果你有一个类Klazz
和模块Mod
,包括Mod
in Klazz
给出了Klazz
访问Mod
方法的实例.或者你可以Klazz
通过Mod
赋予类 Klazz
访问Mod
方法来扩展.但是你也可以扩展一个任意对象o.extend Mod
.在这种情况下,单个对象获取Mod
方法,即使具有相同类的所有其他对象o
也没有.
那是对的.
在幕后,include实际上是append_features的别名,(来自文档):
Ruby的默认实现是将此模块的常量,方法和模块变量添加到aModule(如果此模块尚未添加到aModule或其祖先之一).