Although each class can descend from only one superclass, it can mix in numerous modules. In fact, it is perfectly permissible to mix one lot of modules into another lot of modules, then mix those other modules into classes, then place those classes into yet more modules, and so on.
The following is an example of some code that subclasses some classes, mixes in some modules, and even subclasses classes from within mixed-in modules. I’ve deliberately simplified the following code to help you see what is happening. For the full horror of a working example, see the sample program, multimods.rb, which is supplied in the code archive for this chapter:
multimods.rb
# This is an example of how NOT to use modules! module MagicThing # module class MagicClass # class inside module end end module Treasure # module end module MetalThing include MagicThing # mixin class Attributes < MagicClass # subclasses class from mixin end end include MetalThing # mixin class Weapon < MagicClass # subclass class from mixin class WeaponAttributes < Attributes # subclass end end class Sword < Weapon # subclass include Treasure # mixin include MagicThing # mixin end
Let me emphasize that the code shown previously and included in the archive is not intended as a model to be emulated. Far from it! It is included purely to demonstrate how rapidly a program that makes overenthusiastic use of modules may become difficult to understand and nearly impossible to debug.
In brief, although modules may, when used with care, help avoid some of the complexities associated with the C++ type of multiple inheritance, they are nonetheless open to misuse. If programmers really want to create convoluted hierarchies of classes with inscrutable dependencies on multiple levels of mixed-in modules, then they can certainly do so. The code in multimods.rb shows how easy it is to write an impenetrable program in just a few lines. Imagine what you could do over many thousands of lines of code spread over dozens of code files! Think carefully before mixing in modules.