ruby module_function 与包含模块

标签 ruby module mixins

在 ruby​​ 中,我知道可以使用 module_function 在模块中混合使用模块函数,如此处所示。我知道这是多么有用,因此您可以在不混入模块的情况下使用该函数。

module MyModule
  def do_something
    puts "hello world"
  end
  module_function :do_something
end

我的问题是为什么您可能希望以这两种方式定义函数。

为什么不拥有

def MyModule.do_something

def do_something

在什么样的情况下,将函数混入或用作静态方法会有用?

最佳答案

想到Enumerable .

这是您何时需要将其包含在模块中的完美示例。如果您的类定义了 #each,那么您只需包含一个模块(#map#select 等)就可以获得很多好处。这是我使用模块作为混入的唯一情况——当模块根据一些方法提供功能时,定义在你包含模块的类中。我可以争辩说,这应该是一般情况下的唯一情况。

至于定义“静态”方法,更好的方法是:

module MyModule
  def self.do_something
  end
end

你真的不需要调用#module_function。我认为这只是一些奇怪的遗留问题。

你甚至可以这样做:

module MyModule
  extend self

  def do_something
  end
end

...但如果您还想在某处包含该模块,则效果不佳。我建议在您了解 Ruby 元编程的精妙之处之前避免使用它。

最后,如果你这样做:

def do_something
end

...它最终不会作为全局函数,而是作为 Object 上的私有(private)方法(Ruby 中没有函数,只有方法)。有两个缺点。首先,您没有命名空间——如果您定义了另一个具有相同名称的函数,那么它就是您获得的稍后被评估的函数。其次,如果您有根据 #method_missing 实现的功能,则在 Object 中使用私有(private)方法会隐藏它。最后,猴子修补 Object 只是邪恶的事情:)

编辑:

module_function 的使用方式类似于private:

module Something
  def foo
    puts 'foo'
  end

  module_function

  def bar
    puts 'bar'
  end
end

这样,您可以调用 Something.bar,但不能调用 Something.foo。如果您在调用 module_function 之后定义任何其他方法,它们也可以在不混合的情况下使用。

不过,我不喜欢它有两个原因。首先,混合在一起并具有“静态”方法的模块听起来有点狡猾。可能有有效案例,但不会那么频繁。正如我所说,我更喜欢将模块用作命名空间或将其混合使用,但不能同时使用。

其次,在此示例中,bar 也可用于混合在 Something 中的类/模块。我不确定何时需要这样做,因为该方法要么使用 self 并且必须混入,要么不使用则不需要混入。

我认为在不传递方法名称的情况下使用 module_function 比 with 更常用。 privateprotected 也是如此。

关于ruby module_function 与包含模块,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11550213/

相关文章:

node.js - 将参数传递到模块的最常见方法是什么?

sass - 无法将函数作为参数传递给混入

vuejs2 - 找不到 Mixins Vuejs 中的函数

python - 如何/应该如何在 Python/其他语言中管理跨包模块中的全局数据?

ruby-on-rails - Rails 5 Heroku 部署错误:ExecJS::ProgramError: SyntaxError: 意外的 token :名称(autoRegisterNamespace)

Python 相当于 ruby​​ 的 __method__?

ruby-on-rails - 如何从 html 创建多页 pdf

module - Coq - 统一具有相同参数的模块仿函数的类型?

css - SASS 检查类名

ruby - 在 Rack 中使用和运行的区别