Ruby modules and extend self
Asked Answered
B

3

15

In what sort of situation is the code:

module M
   extend self
   def greet
    puts "hello"
   end

end

more beneficial to use over say something like:

module M
   def self.greet
    puts "hello"
   end
end

In the top, one is an instance method being extended, and the latter is just a class method, but when calling either method, you'd have to M.greet , right? I was just curious if anyone could shed some light on when to use one code over the other. Thanks!

Bakeman answered 28/7, 2010 at 22:24 Comment(0)
S
15

The first example is typically a way people achieve the functionality of module_function (when they do not know the existence of this method).

A module_function is both an instance method and a class method. In your second code example the method is just a class method.

Selfsatisfaction answered 28/7, 2010 at 23:48 Comment(1)
Oh, that's a cool method. That way you can select which methods to give the functionality to in case you don't want to give it to all of them. Thanks!Bakeman
S
10

It would be possible to do this with your first example, but not your second:

include M
greet
Smitherman answered 28/7, 2010 at 22:27 Comment(0)
B
4

A module can be used as a namespace by writing module methods, and a module's instance methods can be mixed into another object.

The self-extending module concept allows a module to be used in both ways; either as a stand-alone namespace or as a mixin. Consider this module:

module M
  def bar
    puts "bar"
  end
end
class C
  include M
end

It has an instance method and can be mixed in to another object. It does not have a module method and cannot, therefore be used as a namespace:

puts M::bar # => undefined method `bar' for M:Module
puts C.bar  # => this is bar

But, a module is an just an object of class Module, as we can demonstrate

puts M.class   # => Module

This means that we can do something crazy. We can mix a module into itself so that its methods become both instance and module methods.

module M
  extend self
  def bar
    puts "bar"
  end
end
puts M::bar # => this is bar
puts C.bar  # => this is bar
Blackstone answered 14/2, 2014 at 11:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.