为什么人们使用`Module.send(:prepend,...)`?

Bre*_*don 5 ruby metaprogramming ruby-2.0 ruby-on-rails-5

我正在学习如何使用Module.prepend而不是alias_method_chain在我的Ruby代码中,我注意到有些人send用来调用它(例子):

ActionView::TemplateRenderer.send(:prepend,
    ActionViewTemplateRendererWithCurrentTemplate)
Run Code Online (Sandbox Code Playgroud)

其他人直接称之为(例子):

ActionView::TemplateRenderer.prepend(ActionViewTemplateRendererWithCurrentTemplate)
Run Code Online (Sandbox Code Playgroud)

而且,虽然我没有看到有人使用这种风格,但我怀疑从文档中你甚至可以在你以前的模块中写这个:

module ActionViewTemplateRendererWithCurrentTemplate
    # Methods you're overriding go here

    prepend_features ActionView::TemplateRenderer
end
Run Code Online (Sandbox Code Playgroud)

这三种风格有什么区别吗?是否有理由支持其他人?

Tom*_*ord 8

Module#prepend添加Ruby版本中2.0.0.

它最初作为私有方法添加,预期用例采用以下格式:

module Foo
  # ...
end

class Bar
  prepend Foo

  # ... The rest of the class definition ...
end
Run Code Online (Sandbox Code Playgroud)

然而,很快就会发现,在很多情况下,人们希望在不定义类的任何其他方面(在代码的那一部分)中将模块添加到类中.因此,以下模式变得普遍:

Bar.send(:prepend, Foo)
Run Code Online (Sandbox Code Playgroud)

Ruby版本中2.1.0,通过创建Module#prepend一个公共方法解决了这个问题- 所以你现在可以简单地将其写成:

Bar.prepend(Foo)
Run Code Online (Sandbox Code Playgroud)

但请注意,如果您正在编写支持Ruby所需的库2.0.0(即使官方支持已于 2016年2月24日结束),那么您必须坚持使用旧.send(:prepend, ...)方法.

Module#include(自成立以来一直使用Ruby语言)在版本中也是一种私有方法<= 2.0.0,并在公开场合公开2.1.0.