““Inheritance” and “Mixin Modules””

rails, Uncategorized

Some object-oriented languages (notably C++) support multiple inheritance, where a class can have more than one immediate parent, inheriting functionality from each. Although powerful, this technique can be dangerous, as the inheritance hierarchy can become ambiguous.

Other languages, such as Java, support single inheritance. Here, a class can have only one immediate parent. Although cleaner (and easier to implement), single inheritance also has drawbacks—in the real world things often inherit attributes from multiple sources (a ball is both a bouncing thing and aspherical thing, for example). Ruby offers an interesting and powerful compromise, giving you the simplicity of single inheritance and the power of multiple inheritance. A Ruby class can have only one direct parent, and so Ruby is a single-inheritance language. However, Ruby classes can include the functionality of any number of mixins (a mixin is like a partial class definition). This provides a controlled multiple-inheritance-like capability with none of the drawbacks.

When a class includes a module, that module’s instance methods become available as instance methods of the class. It’s almost as if the module becomes a superclass of the class that uses it. Not surprisingly, that’s about how it works. When you include a module, Ruby creates an anonymous proxy class that references that module, and inserts that proxy as the direct superclass of the class that did the including. The proxy class contains references to the instance variables and methods of the module. This is important: the same module may be included in many different classes, and will appear in many different inheritance chains. However, thanks to the proxy class, there is still only one underlying module: change a method definition in that module, and it will change in all classes that include that module, both past and future.

<table class=codebox border=0 cellspacing=0 cellpadding=3 width=500><tbody><tr><td colspan=3 valign=top>module SillyModule</td>
</tr><tr><td colspan=3 valign=top>  def hello</td>
</tr><tr><td colspan=3 valign=top>    "Hello."</td>
</tr><tr><td colspan=3 valign=top>  end</td>
</tr><tr><td colspan=3 valign=top>end</td>
</tr><tr><td colspan=3 valign=top>class SillyClass</td>
</tr><tr><td colspan=3 valign=top>  include SillyModule</td>
</tr><tr><td colspan=3 valign=top>end</td>
</tr><tr><td colspan=3 valign=top>s = SillyClass.new</td>
</tr><tr><td valign=top>s.hello</td>
<td valign=top>»</td>
<td valign=top>"Hello."</td>
</tr></tbody></table><table class=codebox border=0 cellspacing=0 cellpadding=3 width=500><tbody><tr><td colspan=3 valign=top>module SillyModule</td>
</tr><tr><td colspan=3 valign=top>  def hello</td>
</tr><tr><td colspan=3 valign=top>    "Hi, there!"</td>
</tr><tr><td colspan=3 valign=top>  end</td>
</tr><tr><td colspan=3 valign=top>end</td>
</tr><tr><td valign=top>s.hello</td>
<td valign=top>»</td>
<td valign=top>"Hi, there!"</td>
</tr></tbody></table>

. If multiple modules are included, they are added to the chain in order.

If a module itself includes other modules, a chain of proxy classes will be added to any class that includes that module, one proxy for each module that is directly or indirectly included.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s