在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上的一个私有方法(Ruby中没有函数,只有方法).有两个缺点.首先,你没有名称空间——如果你定义了另一个同名的函数,它就是你以后得到的那个函数.第二,如果你的功能是按照#method_missing实现的,那么在Object中有一个私有方法会给它蒙上阴影.最后,猴子修补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之后定义了任何其他方法,那么它们也可以在没有混合的情况下使用.

不过,我不喜欢它有两个原因.首先,混合使用"静态"方法的模块听起来有点诡异.可能会有有效的 case ,但不会经常出现.正如我所说的,我更喜欢使用模块作为名称空间,或者将其混合在一起,但不能两者兼而有之.

其次,在本例中,bar也可用于混合在Something中的类/模块.我不确定这是什么时候需要的,因为要么该方法使用self,必须混合,要么不使用,然后就不需要混合.

我认为使用module_function而不传递方法名称的情况比使用module_function更常见.privateprotected也是如此.

Ruby相关问答推荐

如何判断 postgres 中使用 ruby​​ 的查询是否失败?

字符串长度多显示一个字符 - ruby

ruby:rubocop 抱怨将 if else 转换为 case 语句

Ruby $:.unshift File.dirname(__FILE__)

使用 Bundler 时,为什么要关心 RVM 的 Gemset 功能?

Scala 的扩展性是否优于其他 JVM 语言?

Ruby 连接字符串并添加空格

删除 Ruby 数组中的 nil 和空白字符串

Rake 与 Thor 的自动化脚本?

线程安全:Ruby 中的类变量

如何在 Ruby 符号中转义破折号-?

在 ruby​​ 的超类中调用另一个方法

什么是匹配不在行尾的字符串的正则表达式?

通过 x 个字符在 Ruby 中获取子字符串

使用 `?`(问号)在 Ruby 中获取 ASCII 字符代码失败

如何在数组中找到出现次数最多的项目

如何在 Ruby 中获取命名空间中的所有类名?

创建一个接受参数散列的 ruby​​ 方法

项目目录的相对路径

不能在windows上安装thin