-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathruby-way-to-multiple-inheritance.html
135 lines (114 loc) · 5.57 KB
/
ruby-way-to-multiple-inheritance.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
<!DOCTYPE html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
<!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
<!--[if IE 8]> <html class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js"> <!--<![endif]-->
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Ruby way to multiple inheritance ← Vinicius Horewicz</title>
<meta name="viewport" content="width=device-width">
<meta name="author" content="Vinicius Horewicz (wicz)">
<meta name="description" content="wicz' personal notes">
<link rel="alternate" type="application/atom+xml" href="/atom.xml" title="RSS feed" />
<link rel="stylesheet" href="/assets/stylesheets/normalize.css">
<link rel="stylesheet" href="/assets/stylesheets/monokai.css">
<link rel="stylesheet" href="/assets/stylesheets/main.css">
<link rel="stylesheet" href="/assets/stylesheets/screen.css">
<link href="//netdna.bootstrapcdn.com/font-awesome/4.0.0/css/font-awesome.css" rel="stylesheet">
<link href="//fonts.googleapis.com/css?family=Roboto:400,300,300italic|Roboto+Slab:300|Ubuntu+Mono" rel="stylesheet" type="text/css">
<script src="/assets/javascripts/modernizr-2.6.2.min.js"></script>
</head>
<body>
<div class="container">
<p><a href="/">← index</a></p>
<section class="post-content">
<header>
<h1>Ruby way to multiple inheritance</h1>
<time datetime="2013-03-29T00:00:00+01:00" pubdate>29 March 2013</time>
</header>
<article>
<p>Ruby achieves multiple inheritance by mixing modules inside other
classes. That is the reason modules used this way are called
“mixins”.</p>
<p>Mixins are great to share common code among unrelated classes. It
augments objects behavior while reducing code duplication.</p>
<p>Another great aspect about mixins is that its benefits comes with a
little effort to implement. It is based on a thin contract with the
object it is mixed into, which leads to very loosed coupling. For
example, to mix Comparable or Enumerable, all it needs is the host
object to implement the methods <code><=></code> or <code>each</code>, respectively.</p>
<p>There are details, however, the developer needs to be aware. When
including a mixin, Ruby inserts the module into the class’ ancestors
list, as sort of a pseudo superclass. This may make the method lookup
path to become unwieldy and manifest performance issues.</p>
<p>Using mixins wildly may result on “method stuffing”. The amount of
inherited methods not related to the problem domain may increase
significantly, ending in bloated contracts. Ruby’s Enumerable, for
instance, adds more than 40 public methods to the host object’s interface.</p>
<p>There is a risk of name clashing, especially with instance variables of
the host class or other mixins. If the mixin needs its own state, make
sure the instance variables have unique names, e.g. use the module
name as a prefix. The same problem can happen with methods, leading to
unexpected results.</p>
<p>Even though the relationship between the module and host class is looser,
it is still sort of a <em>is-a</em> association. It even returns <code>true</code> to the
<code>is_a?(ModuleName)</code> method call. Being an inheritance, its use should be
carefully compared against composition.</p>
<p>Developers should notice that mixins must be used to share common code,
and <strong>not</strong> as “functions bags”. When used as the latter—to reduce lines
of code, make classes look slim, and whatnot—it gives a false sense of
organization and makes reading code much harder. The key is to create
mixins based on <em>semantics</em>, not on <em>syntatics</em>.</p>
<p>Module-to-module dependency is a design smell. It often hints a missing
class, e.g. service, begging to be created. Mixins should also be
orthogonal, just like the other classes in the system.</p>
<p>Mixins are a convenient solution for many cases, but it requires a lot
of discipline to use effectively. Just as another tool in your toolbox,
use it wisely and with the right purpose.</p>
</article>
</section>
<!-- Enable Disqus comments -->
<div id="disqus_thread"></div>
<script type="text/javascript">
var disqus_shortname = 'horewicz';
var disqus_identifier = '/ruby-way-to-multiple-inheritance';
var disqus_url = 'http://horewi.cz/ruby-way-to-multiple-inheritance.html';
(function() {
var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
(document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
})();
</script>
<footer>
<a href="about.html">
<i class="fa fa-info-circle fa-fw fa-lg"></i>
</a>
<a href="https://www.linkedin.com/in/viniciushorewicz">
<i class="fa fa-l1nkedin fa-fw fa-lg"></i>
</a>
<a href="https://github.com/wicz">
<i class="fa fa-github fa-fw fa-lg"></i>
</a>
<a href="https://twitter.com/wicz">
<i class="fa fa-tw1tter fa-fw fa-lg"></i>
</a>
<a href="https://stackoverflow.com/users/3243455/wicz">
<i class="fa fa-stack-overflow fa-fw fa-lg"></i>
</a>
<a href="/assets/wicz.pub.asc">
<i class="fa fa-lock fa-fw fa-lg"></i>
</a>
<a href="/atom.xml">
<i class="fa fa-rss fa-fw fa-lg"></i>
</a>
</footer>
</div>
<script type="text/javascript">
var _gaq=[['_setAccount','UA-8480243-3'],['_trackPageview']];
(function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
g.src=('https:'==location.protocol?'//ssl':'//www')+'.google-analytics.com/ga.js';
s.parentNode.insertBefore(g,s)}(document,'script'));
</script>
</body>
</html>