In ruby, I understand that module functions can be made available without mixing in the module by using module_function
as shown here. I can see how this is useful so you can use the function without mixing in the module.
module MyModule def do_something puts "hello world" end module_function :do_something end
My question is though why you might want to have the function defined both of these ways.
Why not just have
def MyModule.do_something
OR
def do_something
In what kind of cases would it be useful to have the function available to be mixed in, or to be used as a static method?
module_function(*args) private. Creates module functions for the named methods. These functions may be called with the module as a receiver, and also become available as instance methods to classes that mix in the module. Module functions are copies of the original, and so may be changed independently.
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.
What is the difference between a class and a module? Modules are collections of methods and constants. They cannot generate instances. Classes may generate instances (objects), and have per-instance state (instance variables).
Actually, Ruby facilitates the use of composition by using the mixin facility. Indeed, a module can be included in another module or class by using the include , prepend and extend keywords.
Think of Enumerable.
This is the perfect example of when you need to include it in a module. If your class defines #each
, you get a lot of goodness just by including a module (#map
, #select
, etc.). This is the only case when I use modules as mixins - when the module provides functionality in terms of a few methods, defined in the class you include the module it. I can argue that this should be the only case in general.
As for defining "static" methods, a better approach would be:
module MyModule def self.do_something end end
You don't really need to call #module_function
. I think it is just weird legacy stuff.
You can even do this:
module MyModule extend self def do_something end end
...but it won't work well if you also want to include the module somewhere. I suggest avoiding it until you learn the subtleties of the Ruby metaprogramming.
Finally, if you just do:
def do_something end
...it will not end up as a global function, but as a private method on Object
(there are no functions in Ruby, just methods). There are two downsides. First, you don't have namespacing - if you define another function with the same name, it's the one that gets evaluated later that you get. Second, if you have functionality implemented in terms of #method_missing
, having a private method in Object
will shadow it. And finally, monkey patching Object
is just evil business :)
EDIT:
module_function
can be used in a way similar to private
:
module Something def foo puts 'foo' end module_function def bar puts 'bar' end end
That way, you can call Something.bar
, but not not Something.foo
. If you define any other methods after this call to module_function
, they would also be available without mixing in.
I don't like it for two reasons, though. First, modules that are both mixed in and have "static" methods sound a bit dodgy. There might be valid cases, but it won't be that often. As I said, I prefer either to use a module as a namespace or mix it in, but not both.
Second, in this example, bar
would also be available to classes/modules that mix in Something
. I'm not sure when this is desirable, since either the method uses self
and it has to be mixed in, or doesn't and then it does not need to be mixed in.
I think using module_function
without passing the name of the method is used quite more often than with. Same goes for private
and protected
.
It's a good way for a Ruby library to offer functionality that does not use (much) internal state. So if you (e.g.) want to offer a sin
function and don't want to pollute the "global" (Object
) namespace, you can define it as class method under a constant (Math
).
However, an app developer, who wants to write a mathematical application, might need sin
every two lines. If the method is also an instance method, she can just include the Math
(or My::Awesome::Nested::Library
) module and can now directly call sin
(stdlib example).
It's really about making a library more comfortable for its users. They can choose themself, if they want the functionality of your library on the top level.
By the way, you can achieve a similar functionality like module_function
by using: extend self
(in the first line of the module). To my mind, it looks better and makes things a bit clearer to understand.
Update: More background info in this blog article.
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