1. Computing

Mixin Modules

By

Mixins are one of Ruby's defining features, but often one of the most difficult to understand for those new to Ruby. They're not difficult to understand, but they're not something most programmers have encountered before as most languages don't have mixins. A mixin is a way for code to be shared across multiple classes and is closely related to duck typing.

Duck typing is a technique that allows you to use objects that can respond to a certain set of method calls interchangeably. For example, objects that respond to the method calls rotate, move and draw could all be used as graphics objects in a game program. The game program doesn't care what type these objects really are, just that they can respond to those method calls. After all, if the object walks like a duck and quacks like a duck, it must be a duck.

Mixins can be used to expand the duck typing functionality even further. Continuing with the drawable elements for a game program example, we'll assume that drawable objects must have rotate, move, scale and draw methods. In order to provide a more complete interface, with relative and absolute moves, partial or complete draws, etc, there are two ways to go about it. Since what we're really talking about here is sharing common code to do all this work using the primitive methods described above, you could either use inheritance or mixins.

Inheritance would work just fine. All drawable objects just subclass the Drawable class that has all these methods. However, all your drawable objects must now be subclassed from Drawable or be wrapped in a Drawable class. This type of rigid class hierarchy is very un-Ruby.

Mixins provide a much more Ruby-like solution to this problem. Mixins are a group of methods not yet attached to any class. They exist in a module, and are not useful until included in a class. Once included, the methods in the mixin module are now normal methods of the class.

Continuing with our hypothetical drawable shapes example, here's pseudocode for two shapes. One, a raster image, uses image manipulation libraries to provide scaling and rotation. The other, a geometric polygon, uses geometry to do scaling and rotation. The underlaying mechanism for doing these tasks couldn't be more different.

 class Polygon
   include Drawable
 
   def draw
     # Use geometric line drawing
   end
 
   def move(newx, newy)
     # Move all points to be centered around newx,newy
   end
 end
 
 class Image
   include Drawable
 
   def draw
     # Use blitting to draw image
   end
 
   def move(newx, newy)
     # Move image so top left corner is at newx,newy
   end
 end
 

Now, the following mixin will provide a more detailed interface for the game programmer to use. They'll be able to rotate without having to worry about center points, scale along any axis, etc. These are all things that can be implemented using just the primitive methods provided in the drawable classes, the mixin methods have no special access or knowledge of any class its methods are included into.

 module Drawable
   def slide(deltax, deltay)
     # Use move method to implement slide
   end
 end
 
  1. About.com
  2. Computing
  3. Ruby
  4. Beginning Ruby
  5. Mixin Modules

©2014 About.com. All rights reserved.