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

时间:2017-01-03 08:47:03

标签: ruby metaprogramming ruby-on-rails-5 ruby-2.0

我在Ruby代码中学习如何使用Module.prepend代替alias_method_chain,并且我注意到有些人使用send来调用它({ {3}}):

ActionView::TemplateRenderer.send(:prepend,
    ActionViewTemplateRendererWithCurrentTemplate)

其他人直接称呼它(example):

ActionView::TemplateRenderer.prepend(ActionViewTemplateRendererWithCurrentTemplate)

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

module ActionViewTemplateRendererWithCurrentTemplate
    # Methods you're overriding go here

    prepend_features ActionView::TemplateRenderer
end

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

1 个答案:

答案 0 :(得分:8)

Module#prepend added Ruby版本2.0.0

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

module Foo
  # ...
end

class Bar
  prepend Foo

  # ... The rest of the class definition ...
end

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

Bar.send(:prepend, Foo)

Ruby版本2.1.0 中,此问题已由making Module#prepend a public method解决 - 因此您现在只需将其写为:

Bar.prepend(Foo)

但是,请注意,如果您正在编写支持Ruby 2.0.0所需的库(即使2016年2月24日official support ended),那么您必须坚持使用旧的{{1}方法。

.send(:prepend, ...)(自成立以来一直使用Ruby语言)也是版本Module#include中的私有方法,并在<= 2.0.0中公开。