何时在模块的方法中使用 self

When to use self in module's methods

我的模块定义如下所示:

module RG::Stats
  def self.sum(a, args = {})
    a.inject(0){ |accum, i| accum + i }
  end
end

要使用此方法,我只需要包含此定义的文件即可:

RG::Stats.sum(array)

还有

RG::Stats.method(:sum)

但是,如果我需要知道使用 RG::Stats.instance_methods 的方法列表,我会得到一个空数组。这是因为我使用了self。如果我省略 self,那么 RG::Stats.instance_methods 会给出方法列表,但我无法再访问它们。

问题是:如何在模块的方法定义中使用self

如果你使用self,那么你可以直接使用模块方法使用: RG::Stats.sum(array) 如上所述。

如果您不使用 self 在模块中定义方法,那么对于包含模块的 class,该方法将被包含为 instance_method

因此,您可以在 RG::Stats 模块中定义 sum 实例方法:

module RG::Stats
  def sum(a, args = {})
    a.inject(0){ |accum, i| accum + i }
  end
end

然后,您可以在 class 中包含 RG::Stats 模块,然后 sum 方法将作为 instance_method 用于 [=38= 的对象]:

class YourClass
  include RG::Stats

  . . .
  . . .
end

并且您可以在 YourClass 的实例上调用 sum 方法: YourClass.new.sum

要回答您的问题,您可以使用 self 将您的方法定义为模块内的 class 方法,而不使用 self 将方法定义为实例方法,并且它取决于您的需要和用例,当您想要从模块方法中获得什么类型的行为时。

因为def self.sum没有定义实例方法;您使用了错误的方法 select 它。试试这个:

RG::Stats.methods(false)
# => [:sum]

如果您希望仅在模块的单例 class 中定义方法(其中使用 self 定义的方法存在),请在每个方法定义中使用 self。如果希望模块的方法同时定义为实例方法和单例方法,则省略self和extend self

例如,您可以使用 RG::Stats.sum(array) 调用该方法,如果您这样做,它仍然会被 instance_methods 方法列出:

module RG::Stats
  extend self

  def sum(a, args = {})
    a.inject(0){ |accum, i| accum + i }
  end
end

这样,sum方法定义为实例方法,使用extend self.

后包含在模块的单例class中

您可以检查 RG::Stats 模块的实例方法来验证这一点:

RG::Stats.instance_methods
=> [:sum]

使用这种技术,您不必担心没有 self 关键字定义方法,因为模块不能有实例,所以它不能像 RG::Stats 模块的实例方法那样被调用.由于 extend self 语句,它只能作为单例方法调用 RG::Stats.sum(array)

Class: RuboCop::Cop::Style::ModuleFunction 规则建议使用 module_function 使所有方法成为自我。

参考:https://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Style/ModuleFunction

# bad
module Test
  extend self
  # ...
end

# good
module Test
  module_function
  # ...
end