One of the never-ending style battles in Ruby land is module_function
vs extend self
.
Both enable you to define module methods, which can be called not only from instance level, but also from class level. This enables you to make modules that can optionally be include
'd into your current scope, which makes sense if the module contains non-state changing methods ("functions"). Not having to prepend the module name every time you use the functions saves time and looks good:
# class level
Mathematics.calc # => 42
# instance level
include Mathematics
calc # => 42
module_function
You can achieve this kind of functionality using:
module Mathematics
module_function
def calc
42
end
end
Which is very similar to writing this:
module Mathematics
def self.calc
42
end
private
def calc
42
end
end
Reflection Observations
Mathematics.instance_method(:calc).owner #=> Mathematics
Mathematics.public_method_defined?(:calc) #=> false
Mathematics.private_method_defined?(:calc) #=> true
Mathematics.method(:calc).owner #=> #<Class:Mathematics>
Mathematics.method(:calc).owner.singleton_class? #=> true
Two things to take away from this:
- The method will be copied to the class' singleton class
- The instance method's visibility will become private
extend self
There is another way to get something very similar:
module Mathematics
extend self
def calc
42
end
end
Using extend, the module will add its instance methods to the module's very own inheritance chain.
Reflection Observations
Mathematics.instance_method(:calc).owner #=> Mathematics
Mathematics.public_method_defined?(:calc) #=> true
Mathematics.private_method_defined?(:calc) #=> false
Mathematics.method(:calc).owner #=> Mathematics
Mathematics.method(:calc).owner.singleton_class? #=> false
The differences to module_function
are:
- No method copying involved
- No changes to method visibility
Which One to Use?
Advantages of extend self
- No method copying: If you want to modify a method's behavior via meta-programming, you only need to do this in one place
- No side effects, like changing the method's visibility
- It is not an extra language feature
Advantages of module_function
- The method name "module_function" describes what it does, so it might be more readable
- Making included methods private might be desired
More Idiosyncratic Ruby
- Please Comment on GitHub
- Next Article: Globalization
- Previous Article: Easier Switching