Class Level Mixins

Posted over 2 years ago in Ruby Tutorials.

A question that comes up pretty often in Ruby circles was posed again today, by Xavier Noria:

# Is there standard idiom to add module methods to classes that mixin them?
#
# That is, I would like class C to croak:

module M
  def self.croak
    puts "Croak!"
  end
end

class C
  include M
  croak  # doesn't work
end

This brings up a couple of interesting points about mixins. Obviously, class methods are not easily added to things, but we generally want class methods so we can call them directly from the module. Here's how I deal with this issue.

First, instance methods are the way to go for anything you will be mixing in, period. With instance methods, you can inject them into a class or object. With anything else you have to start hacking. That gives us our first change:

module M
  def croak
    puts "Croak!"
  end
end

Now, we really wanted a module method, so I've made things worse. However, as I've said, we have all the choices with this setup. Let's just mix the module into it's own class!

module M
  extend self  # creates self.croak
  def croak
    puts "Croak!"
  end
end

This trick of duplicating all instance methods as module methods is quite handy. I use it in Rails to make testing helper methods trivial, for example. You basically get two interfaces for the price of one. You can call module methods or mix it into objects.

We've already seen how to fix Xavier's class using the new module, but here it is in writing:

class C
  extend M
  croak  # works fine now
end

Remember, module methods are more powerful if they are instance methods, because you then have all the easy choices. Just mix them into whatever you like, even if it is the module itself.

Gregory Brown added 9 days later:

Hmm... this now makes extend really clear to me, I've never hit a case where I absolutely needed it but plenty of places where this would have been handy if I knew how to use it.

Thanks James!

Add Your Thoughts

You can use Markdown in the body of your comment to format text and make links.

Note that I reserve the right to edit any content you post here. I typically exercise this right to fix formatting issues. All posts must be approved so spam will never been seen on these pages.

Author:
URL or Email (optional):
Body: