views:

645

answers:

4

In Ruby, since you can include multiple mixins but only extend one class, it seems like mixins would be preferred over inheritance.

My question: if you're writing code which must be extended/included to be useful, why would you ever make it a class? Or put another way, why wouldn't you always make it a module?

I can only think of one reason why you'd want a class, and that is if you need to instantiate the class. In the case of ActiveRecord::Base, however, you never instantiate it directly. So shouldn't it have been a module instead?

A: 

Right now, I'm thinking about the template design pattern. It just wouldn't feel right with a module.

Geo
+17  A: 

I just read about this topic in The Well-Grounded Rubyist (great book btw). The author does a better job of explaining than I would so I'll quote him:

No single rule or formula always results in the right design. But it’s useful to keep a couple of considerations in mind when you’re making class-versus-module decisions:

  • Modules don’t have instances. It follows that entities or things are generally best modeled in classes, and characteristics or properties of entities or things are best encapsulated in modules. Correspondingly, as noted in section 4.1.1, class names tend to be nouns, whereas module names are often adjectives (Stack versus Stacklike).

  • A class can have only one superclass, but it can mix in as many modules as it wants. If you’re using inheritance, give priority to creating a sensible superclass/subclass relationship. Don’t use up a class’s one and only superclass relationship to endow the class with what might turn out to be just one of several sets of characteristics.

Summing up these rules in one example, here is what you should not do:

module Vehicle 
... 
class SelfPropelling 
... 
class Truck < SelfPropelling 
  include Vehicle 
...

Rather, you should do this:

module SelfPropelling 
... 
class Vehicle 
  include SelfPropelling 
... 
class Truck < Vehicle 
...

The second version models the entities and properties much more neatly. Truck descends from Vehicle (which makes sense), whereas SelfPropelling is a character- istic of vehicles (at least, all those we care about in this model of the world)—a charac- teristic that is passed on to trucks by virtue of Truck being a descendant, or specialized form, of Vehicle.

Andy Gaskell
+1 for the articulate answer
Roee Adler
Great answer +1
Yar
+1  A: 

My take: Modules are for sharing behavior, while classes are for modeling relationships between objects. You technically could just make everything an instance of Object and mix in whatever modules you want to get the desired set of behaviors, but that would be a poor, haphazard and rather unreadable design.

Chuck
+2  A: 

The answer to your question is largely contextual. Distilling pubb's observation, the choice is primarily driven by the domain under consideration.

And yes, ActiveRecord should have been included rather than extended by a subclass. Another ORM - datamapper - precisely achieves that!

nareshb