Is defining a module function with module_function the same as defining it with self. in Ruby? That is, do they both result in the creation of both instance and module methods?
2 Answers
No, they are not the same. Using self. creates only a module method, whereas module_function creates both a module and an instance method:
#!/usr/bin/env ruby
module M1
def self.foo
puts 'foo'
end
end
module M2
module_function
def foo
puts 'foo'
end
end
class C1
include M1
def test
puts 'Call M1 as module method:'
M1.foo
# puts 'Call M1 as instance method:'
# foo
end
end
class C2
include M2
def test
puts 'Call M2 as module method:'
M2.foo
puts 'Call M2 as instance method:'
foo
end
end
C2.new.test; C1.new.test
Results in the following output:
Call M2 as module method:
foo
Call M2 as instance method:
foo
Call M1 as module method:
foo
If you then uncomment out the 'Call M1 as instance method:' 2 lines, you'll see this error:
./m1.rb:24:in `test': undefined local variable or method `foo' for #<C1:0x007feb311767f8> (NameError)
This shows that an instance method foo was not created when the method was defined as self.foo.
5 Comments
Cary Swoveland
Note:
c2.foo #=> NoMethodError: private method 'foo'...; c2.send(:foo) #=> foo.Keith Bennett
@CarySwoveland I don't understand what you're saying, could you explain? Also, BTW, I fixed my copy/paste error, all were printing out as M1.
Cary Swoveland
Sorry, I just thought it was worth mentioning that Module#module_function makes the instance method private.
Keith Bennett
I see, that's interesting. I've only ever called such methods in the including class so that never occurred to me. Thanks!
Cary Swoveland
I see in my comment I forgot
c2=C2.new. No wonder it was puzzling.