Ruby中的include和extend有什么区别?

只是想了解一下Ruby元编程。mixin/模块总是让我感到困惑

  • include:将指定的模块方法作为实例方法混入目标类中
  • extend:将指定的模块方法作为类方法混入目标类中

那么主要的区别是这条龙还是潜伏着一条更大的龙
e、 g

模块可重用模块
def模块法
将“模块方法:您好!”
终止
终止
包括的类
包括可重用模块
终止
扩展的类
扩展可重用模块
终止
放入“包括”
ClassThatIncludes.new.module#方法#“模块方法:您好!”
将“扩展”
ClassThatExtends.module#方法#“模块方法:您好!”

extend-将指定模块的方法和常量添加到目标的元类(即singleton类)
e、 g

  • 如果调用Klazz.extend(Mod),现在Klazz有Mod的方法(作为类方法)
  • 如果调用obj.extend(Mod),现在obj有Mod的方法(作为实例方法),但是obj.class的其他实例中没有添加这些方法
  • extend是一种公共方法

include-默认情况下,它在目标模块/类中混合指定模块的方法作为实例方法。
e、 g

  • 如果你调用类Klazz;包括国防部;结束,现在Klazz的所有实例都可以访问Mod的方法(作为实例方法)
  • include是一个私有方法,因为它是从容器类/模块中调用的

然而,模块通常通过猴子修补包含的方法来覆盖包含的行为。这在遗留Rails代码中非常突出。更多详情请参见Yehuda Katz

关于的更多详细信息包括,以及它的默认行为,假设您运行了以下代码

类Klazz
包括国防部
终止
  • 如果Mod已经包含在Klazz或其祖先之一中,则include语句无效
  • 它还包括Klazz中的Mod常量,只要它们不冲突
  • 它允许Klazz访问Mod的模块变量,例如@@foo@@bar
  • 如果存在循环包含,则引发ArgumentError
  • 将模块附加为调用方的直接祖先(即,它将Mod添加到Klazz.祖先,但Mod未添加到Klazz.superclass.superclass.superclass.superclass的链中。因此,在Klazz#foo中调用super,将在检查Klazz真正的超类的foo方法之前检查Mod#foo。有关详细信息,请参阅RubySpec)

当然,ruby核心文档始终是实现这些功能的最佳场所。RubySpec项目也是一个极好的资源,因为它们精确地记录了功能

  • #包括RubySpec rubydoc
  • #包括RubySpec rubydoc
  • #扩展RubySpec-rubydoc
  • 扩展的RubySpec rubydoc
  • #扩展对象RubySpec rubydoc
  • #附加功能RubySpec rubydoc

发表评论