31

模块

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

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

谁能帮我理解以下问题:

  • 除了那些默认功能之外,还有哪些功能Module被定义为?appendprepend

  • 它们在功能上有何不同?

  • 何时使用append_features,何时使用prepend_features

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

4

2 回答 2

39
  • Module 的哪些特性被定义为 append 和 prepend?

如您引用的文本中所述:

常量、方法和模块变量

  • 它们在功能上有何不同?

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

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当您想将目标模块(类)的方法保留在方法查找链的末尾时使用。

ruby通过搜索 SO和可以找到一些真实世界的module示例prepend

(注意:我只提到方法,因为它们在继承和混合方面最容易想象,但同样适用于其他特性。)

于 2013-03-13T12:00:00.673 回答
6

我想将它作为评论添加到@Mladen Jablanovic 已经做出的一个很好的答案中,但由于我的声誉低,我不能这样做。

我在这里的帖子中找到了更简洁、更清晰和更具描述性的答案——Ruby modules: Include vs Prepend vs Extend,我在这里发布它以防万一有人需要它并且可以用更少的努力得到它。

直接报价:

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

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

创建 Ruby 类时,它包含一个常量名称列表,这些常量名称是其祖先。它们是类继承自的所有类,以及它们包含的模块。例如,通过调用 String 类的祖先,我们得到它的祖先列表:

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

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

从 Ruby 2 开始,prepend 对 Rubyists 的了解比它的另外两个朋友要少一些。它实际上像包含一样工作,只是它不是在链中的类和它的超类之间插入模块,而是将它插入到链的底部,甚至在类本身之前。

我建议阅读这篇文章,以便更好地理解它附带的示例。

于 2018-08-02T23:04:28.213 回答