When to use self in module's methods

这一生的挚爱 提交于 2019-12-09 09:28:38

问题


My module definition looks like this:

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

To use this method I simply require the file containing this definition so that I can do:

RG::Stats.sum(array)

and also

RG::Stats.method(:sum)

However, if I need to know the list of methods using RG::Stats.instance_methods I get an empty array. This is because I have used self. If I omit self then RG::Stats.instance_methods gives the list of methods, but I cannot access them anymore.

The question is: how to use self in module's method definition?


回答1:


Use self in each method definition if you want the methods to be defined only in the singleton class of the module (where the methods defined using self live). Omit self and extend self if you want the methods of the module to be defined as instance methods and singleton methods at the same time.

For instance, you can call the method using RG::Stats.sum(array) and still have it listed by the instance_methods method if you do this:

module RG::Stats
  extend self

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

This way, the sum method is defined as an instance method and it is included in the singleton class of the module after using extend self.

You can check the instance methods of RG::Stats module to verify this:

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

With this technique you don't have to worry about defining the method without the self keyword because modules can't have instances so it cannot be called like an instance method of RG::Stats module. It can only be called as a singleton method RG::Stats.sum(array) thanks to the extend self statement.




回答2:


It is because def self.sum does not define an instance method; you are using the wrong method to select it. Try this instead:

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



回答3:


If you use self, then you can use the module method directly using: RG::Stats.sum(array) as you mentioned above.

If you don't use self to define the method inside your module, then the method will be included as instance_method for a class where you include the module.

So, you can define the sum instance method inside your RG::Stats module:

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

Then, you can include RG::Stats module inside a class and then the sum method will be available as a instance_method for objects of the class:

class YourClass
  include RG::Stats

  . . .
  . . .
end

And you can call the sum method on an instance of YourClass: YourClass.new.sum

To answer your question, you can use self to define your method as a class method inside your module, and without self to define the method as instance method and it depends on your need and usecase that when you want what type of behaviour from your module methods.



来源:https://stackoverflow.com/questions/32751805/when-to-use-self-in-modules-methods

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!