Ruby中'include'和'prepend'有什么区别?

时间:2013-03-13 11:22:17

标签: ruby mixins prepend ruby-2.0

来自Module

  

模块#append_features(mod)→mod =>当这个模块包含在另一个模块中时,Ruby在这个模块中调用append_features,并在mod中传递接收模块。如果此模块尚未添加到mod或其祖先之一,Ruby的默认实现是 将此模块的常量,方法和模块变量添加到

     

模块#prepend_features(mod)→mod =&gt;当这个模块被放在另一个模块中时,Ruby在这个模块中调用prepend_features,并在mod中传递接收模块。如果此模块尚未添加到mod或其祖先之一,则Ruby的默认实现是 此模块的常量,方法和模块变量叠加到mod。< / p>

任何人都可以帮助我理解以下问题:

  • Module的其他功能定义为appendprepend,但默认情况除外?

  • 它们的功能有何不同?

  • 何时使用append_features和何时prepend_features

  • 上面两条粗线之间有什么区别?

2 个答案:

答案 0 :(得分:21)

  • 模块的哪些功能被定义为追加和前置?

正如您引用的文字中所述:

  

常量,方法和模块变量

  • 他们的功能有何不同?

两者都将混合模块的方法添加到传递的模块(类)中。不同之处在于这些方法的查找顺序,如果目标类已经定义了它们:

include的行为就好像目标类继承了混合模块:

module FooBar
  def say
    puts "2 - Module"
  end
end

class Foo
  include FooBar

  def say
    puts "1 - Implementing Class"
    super
  end
end

Foo.new.say # =>
            # 1 - Implementing Class
            # 2 - Module

prepend使混合模块中的方法“更强”并首先执行它们:

module FooBar
  def say
    puts "2 - Module"
    super
  end
end

class Foo
  prepend FooBar

  def say
    puts "1 - Implementing Class"
  end
end

Foo.new.say # =>
            # 2 - Module
            # 1 - Implementing Class

这个例子从这里扯下来:http://blog.crowdint.com/2012/11/05/3-killer-features-that-are-coming-on-ruby-2-0.html

  • 何时使用append_features和prepend_features?

如果要将目标模块(类)的方法保留在方法查找链的末尾,请使用prepend

通过在SO上搜索rubymoduleprepend可以找到一些真实示例:

(注意:我只提到方法,因为它们在继承和混合方面最容易描绘,但这同样适用于其他功能。)

答案 1 :(得分:3)

我想将它添加为@Mladen Jablanovic已经做出的一个很好的答案的注释,但是由于我的声誉低而无法。

我在这里的帖子Ruby modules: Include vs Prepend vs Extend上找到了一个更简洁,更清晰和更具描述性的答案,我把它发布在这里是为了防止有人需要它并且可以用更少的精力来获得它。

直接引号:

  

尽管include是将外部代码导入到类中的最常见方法,但是Ruby还提供了另外两种方法来实现该目的:扩展和前置。但是,它们根本没有相同的行为,并且这些差异经常被Ruby开发人员误解。

     

要了解如何使用它们,我们首先必须深入了解Ruby如何使用称为祖先的链来解析在运行时执行的方法。

     

创建Ruby类时,它将保存一个常量名称列表,这些常量名称是其祖先。它们是该类继承的所有类以及它们包括的模块。例如,通过在String类上调用祖先,我们可以获得其祖先的列表:

String.ancestors
=> [String, Comparable, Object, PP::ObjectMixin, Kernel, BasicObject]
     

include是导入模块代码的最常用和最简单的方法。当在类定义中调用它时,Ruby会将模块插入到该类的祖先链中,紧接其超类之后。

     

从Ruby 2开始可用,前缀比其他两个朋友对Rubyists的了解少。它实际上就像include一样工作,除了它不是将模块插入链中的类及其超类之间,而是将其插入链的底部,甚至在类本身之前。

我建议您阅读这篇文章,以更好地理解示例。