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?
self is a special variable that points to the object that "owns" the currently executing code. Ruby uses self everwhere: For instance variables: @myvar. For method and constant lookup. When defining methods, classes and modules.
extend self includes all the existing instance methods as module methods. This is equivalent to saying extend Rake . Also Rake is an object of class Module . This can be used to define self contained modules with private methods.
Class Method Self A class method is a method that refers only to that class in all contexts, but not to any individual instances of that class. A class instance method is a method that applies to all instances of that class, but not for the class object itself.
In simple words, the difference between include and extend is that 'include' is for adding methods only to an instance of a class and 'extend' is for adding methods to the class but not to its instance.
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.
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.
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]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With