Keith Bennett
Keith Bennett

Reputation: 4950

Is defining a module function with `module_function` the same as defining it with `self.` in Ruby?

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?

Upvotes: 6

Views: 1161

Answers (2)

Keith Bennett
Keith Bennett

Reputation: 4950

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.

Upvotes: 2

Cary Swoveland
Cary Swoveland

Reputation: 110675

No.

module M1
  def self.foo; end
end

module M2
  module_function
  def goo; end
end

M1.methods(false)           #=> [:foo] 
M1.instance_methods         #=> [] 
M1.private_instance_methods #=> [] 

M2.methods(false)           #=> [:goo] 
M2.instance_methods         #=> [] 
M2.private_instance_methods #=> [:goo] 

Upvotes: 4

Related Questions