Assume that a certain functionality is available in Ruby both as a class method and as an instance method (via a module).
Class method:
require 'foo'
Foo.foo()
Instance method (via module):
require 'bar'
include Bar
bar()
Assuming that the two methods behave identically, which would you prefer using, and why?
(Note that the question is not about which to implement, but instead about which to use if both available.)
Top comments (3)
A
require 'foo'
does not alter your class. It just gives you access to callFoo.foo()
. There's nothing happening in terms of inheritance or composition. It's maybe the simplest form of dependency between your class and Foo. If you only want to call one method or another in Foo, then yes, that's the way to go.But when calling
include Bar
there's a lot happening. You not only get access tobar()
, but also to all other methods that are in Bar. And they are directly available in the namespace of your instance. And maybe even class methods have been defined, so the include might have also given youYourClass.baz()
. You better know exactly what's in Bar, because your class might get cluttered with a lot of stuff... it's actually pretty similar to inheritance. So the actual question when it comes toinclude
is: ruby inheritance vs. mixins. And I like this answer very much:So back to your question - you should use
include
when you want your class to get (all) the behaviour the module gives you. And you should not use it if you just want to call a method.I would prefer the first, because calling
Foo.foo
clearly shows the receiver of the method, and I know thatbar
is probably defined in foo.rb.In the second example, it's less clear where
bar
is defined. Ok, it's clear in your example, but in a situation where the names aren't so simple,bar
might be defined in the current class, or bar.rb, or any other module that's mixed into the current class, or all three.I think the
include
is most useful as used inEnumerable
, e.g. a base class implements a few simple methods, and then by including a module that leverages those simple methods, gets a lot of syntactic sugar on top.class methods, (consider prefixing your module with
module_function
and all methods will be accessible as class methods) are a way of pushing Ruby to be more functional.It's not one vs the other, but rather, two different tools wrapped in one name,
module
.Generally, though, I agree with some of the other commenters that class methods are king. But also: if you're going to lean on class methods so much, it might make sense to try to use another language that enforces those patterns, e.g. most functional programming languages. Elixir? Elm?