|
| 1 | +<!DOCTYPE HTML> |
| 2 | +<html lang="en-US" manifest="./manifest.appcache"> |
| 3 | + |
| 4 | + <head prefix="og: http://ogp.me/ns# book: http://ogp.me/ns/book#"> |
| 5 | + |
| 6 | + |
| 7 | + <meta charset="UTF-8"> |
| 8 | + <title>方法的调用 | Ruby中的元编程</title> |
| 9 | + |
| 10 | + <meta content="text/html; charset=utf-8" http-equiv="Content-Type"> |
| 11 | + <meta name="robots" content="index, follow"> |
| 12 | + <meta name="author" content=""> |
| 13 | + <meta name="description" content=" 本系列翻译自Ruby Metaprogramming站点上的课程笔记,并加入了我(DeathKing)的一些个人演绎、资料补充等。希望对大家有所帮助。"> |
| 14 | + <meta name="keywords" content="gitbook,github" > |
| 15 | + <meta name="generator" content="www.gitbook.io"> |
| 16 | + |
| 17 | + |
| 18 | + <link rel="next" href="./chapter04.html" /> |
| 19 | + |
| 20 | + |
| 21 | + <link rel="prev" href="./chapter02.html" /> |
| 22 | + |
| 23 | + |
| 24 | + <meta property="og:title" content="方法的调用 | Ruby中的元编程"> |
| 25 | + <meta property="og:site_name" content="Ruby中的元编程"> |
| 26 | + <meta property="og:type" content="book"> |
| 27 | + <meta property="og:locale" content="en_US"> |
| 28 | + |
| 29 | + <meta property="book:author" content="https://github.com/"> |
| 30 | + <meta property="book:tag" content="GitBook"> |
| 31 | + |
| 32 | + <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no"> |
| 33 | + <meta name="apple-mobile-web-app-capable" content="yes"> |
| 34 | + <meta name="apple-mobile-web-app-status-bar-style" content="black"> |
| 35 | + |
| 36 | + <link rel="shortcut icon" href="gitbook/images/favicon.ico" type="image/x-icon"> |
| 37 | + |
| 38 | + |
| 39 | + </head> |
| 40 | + <body> |
| 41 | + |
| 42 | + |
| 43 | + |
| 44 | + <link rel="stylesheet" href="gitbook/style.css"> |
| 45 | + |
| 46 | + |
| 47 | + |
| 48 | + |
| 49 | + <div class="book" data-level="3" data-basepath="." data-revision="1401444078312"> |
| 50 | + <div class="book-header"> |
| 51 | + <!-- Actions Left --> |
| 52 | + <a href="#" class="btn pull-left toggle-summary" aria-label="Toggle summary"><i class="fa fa-align-justify"></i></a> |
| 53 | + |
| 54 | + <a href="https://github.com/null" target="_blank" class="btn pull-left home-bookmark" aria-label="GitHub home"><i class="fa fa-bookmark-o"></i></a> |
| 55 | + |
| 56 | + <a href="#" class="btn pull-left toggle-search" aria-label="Toggle search"><i class="fa fa-search"></i></a> |
| 57 | + <span id="font-settings-wrapper"> |
| 58 | + <a href="#" class="btn pull-left toggle-font-settings" aria-label="Toggle font settings"><i class="fa fa-font"></i> |
| 59 | + </a> |
| 60 | + <div class="dropdown-menu font-settings"> |
| 61 | + <div class="dropdown-caret"> |
| 62 | + <span class="caret-outer"></span> |
| 63 | + <span class="caret-inner"></span> |
| 64 | + </div> |
| 65 | + |
| 66 | + <div class="btn-group btn-block"> |
| 67 | + <button id="reduce-font-size" class="btn btn-default">A</button> |
| 68 | + <button id="enlarge-font-size" class="btn btn-default">A</button> |
| 69 | + </div> |
| 70 | + |
| 71 | + <ul class="list-group font-family-list"> |
| 72 | + <li class="list-group-item" data-font="0">Serif</li> |
| 73 | + <li class="list-group-item" data-font="1">Sans</li> |
| 74 | + </ul> |
| 75 | + |
| 76 | + <div class="btn-group btn-group-xs btn-block color-theme-list"> |
| 77 | + <button type="button" class="btn btn-default" id="color-theme-preview-0" data-theme="0">White</button> |
| 78 | + <button type="button" class="btn btn-default" id="color-theme-preview-1" data-theme="1">Sepia</button> |
| 79 | + <button type="button" class="btn btn-default" id="color-theme-preview-2" data-theme="2">Night</button> |
| 80 | + </div> |
| 81 | +</div> |
| 82 | + |
| 83 | + </span> |
| 84 | + |
| 85 | + <!-- Actions Right --> |
| 86 | + |
| 87 | + <a href="#" target="_blank" class="btn pull-right google-plus-sharing-link sharing-link" data-sharing="google-plus" aria-label="Share on Google Plus"><i class="fa fa-google-plus"></i></a> |
| 88 | + |
| 89 | + |
| 90 | + <a href="#" target="_blank" class="btn pull-right facebook-sharing-link sharing-link" data-sharing="facebook" aria-label="Share on Facebook"><i class="fa fa-facebook"></i></a> |
| 91 | + |
| 92 | + |
| 93 | + <a href="#" target="_blank" class="btn pull-right twitter-sharing-link sharing-link" data-sharing="twitter" aria-label="Share on Twitter"><i class="fa fa-twitter"></i></a> |
| 94 | + |
| 95 | + |
| 96 | + |
| 97 | + |
| 98 | + <!-- Title --> |
| 99 | + <h1> |
| 100 | + <i class="fa fa-spinner fa-spin"></i> |
| 101 | + <a href="./" >Ruby中的元编程</a> |
| 102 | + </h1> |
| 103 | +</div> |
| 104 | + |
| 105 | + |
| 106 | + |
| 107 | +<div class="book-summary"> |
| 108 | + <div class="book-search"> |
| 109 | + <input type="text" placeholder="Search" class="form-control" /> |
| 110 | + </div> |
| 111 | + <ul class="summary"> |
| 112 | + |
| 113 | + |
| 114 | + |
| 115 | + |
| 116 | + |
| 117 | + |
| 118 | + |
| 119 | + |
| 120 | + |
| 121 | + <li data-level="0" data-path="index.html"> |
| 122 | + <a href="./"><i class="fa fa-check"></i> Introduction</a> |
| 123 | + </li> |
| 124 | + |
| 125 | + |
| 126 | + <li class="chapter " data-level="1" data-path="chapter01.html"> |
| 127 | + |
| 128 | + <a href="./chapter01.html"> |
| 129 | + <i class="fa fa-check"></i> <b>1.</b> 前言 |
| 130 | + </a> |
| 131 | + |
| 132 | + |
| 133 | + </li> |
| 134 | + |
| 135 | + <li class="chapter " data-level="2" data-path="chapter02.html"> |
| 136 | + |
| 137 | + <a href="./chapter02.html"> |
| 138 | + <i class="fa fa-check"></i> <b>2.</b> 实例变量、方法、类 |
| 139 | + </a> |
| 140 | + |
| 141 | + |
| 142 | + </li> |
| 143 | + |
| 144 | + <li class="chapter " data-level="3" data-path="chapter03.html"> |
| 145 | + |
| 146 | + <a href="./chapter03.html"> |
| 147 | + <i class="fa fa-check"></i> <b>3.</b> 方法的调用 |
| 148 | + </a> |
| 149 | + |
| 150 | + |
| 151 | + </li> |
| 152 | + |
| 153 | + <li class="chapter " data-level="4" data-path="chapter04.html"> |
| 154 | + |
| 155 | + <a href="./chapter04.html"> |
| 156 | + <i class="fa fa-check"></i> <b>4.</b> 实用元编程方法 |
| 157 | + </a> |
| 158 | + |
| 159 | + |
| 160 | + </li> |
| 161 | + |
| 162 | + <li class="chapter " data-level="5" data-path="chapter05.html"> |
| 163 | + |
| 164 | + <a href="./chapter05.html"> |
| 165 | + <i class="fa fa-check"></i> <b>5.</b> 绑定 |
| 166 | + </a> |
| 167 | + |
| 168 | + |
| 169 | + </li> |
| 170 | + |
| 171 | + <li class="chapter " data-level="6" data-path="chapter06.html"> |
| 172 | + |
| 173 | + <a href="./chapter06.html"> |
| 174 | + <i class="fa fa-check"></i> <b>6.</b> 块和绑定 |
| 175 | + </a> |
| 176 | + |
| 177 | + |
| 178 | + </li> |
| 179 | + |
| 180 | + <li class="chapter " data-level="7" data-path="chapter07.html"> |
| 181 | + |
| 182 | + <a href="./chapter07.html"> |
| 183 | + <i class="fa fa-check"></i> <b>7.</b> 元编程实战 |
| 184 | + </a> |
| 185 | + |
| 186 | + |
| 187 | + </li> |
| 188 | + |
| 189 | + <li class="chapter " data-level="8" data-path="chapter08.html"> |
| 190 | + |
| 191 | + <a href="./chapter08.html"> |
| 192 | + <i class="fa fa-check"></i> <b>8.</b> 结语 |
| 193 | + </a> |
| 194 | + |
| 195 | + |
| 196 | + </li> |
| 197 | + |
| 198 | + |
| 199 | + |
| 200 | + |
| 201 | + <li class="divider"></li> |
| 202 | + <li> |
| 203 | + <a href="http://www.gitbook.io/" target="blank" class="gitbook-link">Generated using GitBook</a> |
| 204 | + </li> |
| 205 | + |
| 206 | + </ul> |
| 207 | +</div> |
| 208 | + |
| 209 | + <div class="book-body"> |
| 210 | + <div class="body-inner"> |
| 211 | + <div class="page-wrapper" tabindex="-1"> |
| 212 | + <div class="book-progress"> |
| 213 | + <div class="bar"> |
| 214 | + <div class="inner" style="width: 37.5%;min-width: 25%;"></div> |
| 215 | + </div> |
| 216 | + <div class="chapters"> |
| 217 | + |
| 218 | + <a href="./index.html" title="Introduction" class="chapter done new-chapter" data-progress="0" style="left: 0%;"></a> |
| 219 | + |
| 220 | + <a href="./chapter01.html" title="前言" class="chapter done new-chapter" data-progress="1" style="left: 12.5%;"></a> |
| 221 | + |
| 222 | + <a href="./chapter02.html" title="实例变量、方法、类" class="chapter done new-chapter" data-progress="2" style="left: 25%;"></a> |
| 223 | + |
| 224 | + <a href="./chapter03.html" title="方法的调用" class="chapter done new-chapter" data-progress="3" style="left: 37.5%;"></a> |
| 225 | + |
| 226 | + <a href="./chapter04.html" title="实用元编程方法" class="chapter new-chapter" data-progress="4" style="left: 50%;"></a> |
| 227 | + |
| 228 | + <a href="./chapter05.html" title="绑定" class="chapter new-chapter" data-progress="5" style="left: 62.5%;"></a> |
| 229 | + |
| 230 | + <a href="./chapter06.html" title="块和绑定" class="chapter new-chapter" data-progress="6" style="left: 75%;"></a> |
| 231 | + |
| 232 | + <a href="./chapter07.html" title="元编程实战" class="chapter new-chapter" data-progress="7" style="left: 87.5%;"></a> |
| 233 | + |
| 234 | + <a href="./chapter08.html" title="结语" class="chapter new-chapter" data-progress="8" style="left: 100%;"></a> |
| 235 | + |
| 236 | + </div> |
| 237 | +</div> |
| 238 | + |
| 239 | + <div class="page-inner"> |
| 240 | + |
| 241 | + <section class="normal" id="section-gitbook_7"> |
| 242 | + |
| 243 | + <h1 id="-">方法的调用</h1> |
| 244 | +<p> 当你在调用某一个方法的时候,Ruby会完成下面的步骤:</p> |
| 245 | +<ul> |
| 246 | +<li>找到这个方法,我们把这个过程称作<strong>方法查找(method lookup)</strong>;</li> |
| 247 | +<li>执行这个方法,为了执行这个方法,Ruby需要一个叫做<code>self</code>的伪变量;</li> |
| 248 | +</ul> |
| 249 | +<h2 id="-">方法的查找</h2> |
| 250 | +<p> 要理解Ruby的方法查找,你需要了解下面两个概念:<strong>接受者(receiver)</strong>和<strong>祖先链(ancestors chain)</strong>。接受者就是方法的调用者。例如,对调用<code>an_object.display()</code>来说,<code>an_object</code>就是接受者。而关于祖先链,请考察任何一个Ruby类的内部。想象一下从一个类移动到其父类,然后再移动到父类的父类,直到到达<code>Object</code>类(默认的父类),然后继续移动,最终到达<code>BasicObject</code>类(Ruby层级模型中的根)。你遍历这些类所走过的路径就是“祖先链”(祖先链中也包括模块)。</p> |
| 251 | +<p> 因此,为了查找方法,Ruby首先进入receiver所属的类,并以此为起始,沿着祖先链不断前进,直到找到目标方法。这种行为也被称作<strong>“向右一步,再向上(one step to the right, then up)”</strong>规则:向右一步,进入reciver所属的类,然后再向上查找祖先链,直到找到目标方法。(译者注:如果遍历完祖先链也没有找到方法的话,会调用<code>method_missing</code>方法,如果这个方法没有被定义,则抛出<code>NoMethodError</code>)当你在一个类中包含一个模块时,Ruby创建了一个匿名类来封装这个模块,并将这个匿名类插入到祖先链中,也在这个类的上方。</p> |
| 252 | +<p> 下面的代码演示了一次方法查找:</p> |
| 253 | +<pre><code class="lang-ruby"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">A</span></span> |
| 254 | + <span class="hljs-function"><span class="hljs-keyword">def</span> </span>foo |
| 255 | + <span class="hljs-keyword">end</span> |
| 256 | +<span class="hljs-keyword">end</span> |
| 257 | +<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">B</span> <span class="hljs-inheritance">< <span class="hljs-parent">A</span></span></span> |
| 258 | + <span class="hljs-function"><span class="hljs-keyword">def</span> </span>bar |
| 259 | + <span class="hljs-comment"># bar method in B</span> |
| 260 | + <span class="hljs-keyword">end</span> |
| 261 | +<span class="hljs-keyword">end</span> |
| 262 | +<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">C</span> <span class="hljs-inheritance">< <span class="hljs-parent">B</span></span></span> |
| 263 | + <span class="hljs-function"><span class="hljs-keyword">def</span> </span>bar |
| 264 | + <span class="hljs-comment"># bar method in C</span> |
| 265 | + <span class="hljs-comment"># overwriting superclass' method</span> |
| 266 | + <span class="hljs-keyword">end</span> |
| 267 | +<span class="hljs-keyword">end</span> |
| 268 | + |
| 269 | +obj = <span class="hljs-constant">C</span>.new |
| 270 | +obj.bar <span class="hljs-comment">#=> in C class</span> |
| 271 | +obj.foo <span class="hljs-comment">#=> not in C class</span> |
| 272 | + <span class="hljs-comment">#=> then go to C's superclass B</span> |
| 273 | + <span class="hljs-comment">#=> not in B class</span> |
| 274 | + <span class="hljs-comment">#=> then go to B's superclass A</span> |
| 275 | + <span class="hljs-comment">#=> execute it</span> |
| 276 | +</code></pre> |
| 277 | +<h2 id="self">self</h2> |
| 278 | +<ul> |
| 279 | +<li>在Ruby中,<code>self</code>是一个很特殊的变量,它总是指向当前对象(current object);</li> |
| 280 | +<li><code>self</code>被认为是默认的receiver。也就是说,你如果没有明确指出receiver,那么系统将把<code>self</code>当做receiver;</li> |
| 281 | +<li>实例变量是在<code>self</code>(当前对象)中查找的。也就是说,如果我使用<code>@var</code>,那么Ruby就会在<code>self</code>所指向的对象中去寻找此实例变量。需要注意的是,实例变量并不是由类定义的,它们也和子类以及继承机制无关。</li> |
| 282 | +</ul> |
| 283 | +<p> 因此,当我们在调用一个明确指出receiver的方法时,Ruby会按照下面的步骤执行:</p> |
| 284 | +<pre><code class="lang-ruby">obj.do_method(param) |
| 285 | +</code></pre> |
| 286 | +<ul> |
| 287 | +<li>将<code>self</code>指向<code>obj</code>;</li> |
| 288 | +<li>在<code>self</code>所属的类中查找<code>do_method(param)</code>方法(方法是存放在类中,而不是实例中!);</li> |
| 289 | +<li>调用方法<code>do_method(param)</code>;</li> |
| 290 | +</ul> |
| 291 | + |
| 292 | + |
| 293 | + </section> |
| 294 | + |
| 295 | + </div> |
| 296 | + </div> |
| 297 | + </div> |
| 298 | + |
| 299 | + |
| 300 | + <a href="./chapter02.html" class="navigation navigation-prev " aria-label="Previous page: 实例变量、方法、类"><i class="fa fa-angle-left"></i></a> |
| 301 | + |
| 302 | + |
| 303 | + <a href="./chapter04.html" class="navigation navigation-next " aria-label="Next page: 实用元编程方法"><i class="fa fa-angle-right"></i></a> |
| 304 | + |
| 305 | + </div> |
| 306 | +</div> |
| 307 | + |
| 308 | + |
| 309 | + |
| 310 | + <script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.1.3/ace.js"></script> |
| 311 | + <script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.1.3/mode-javascript.js"></script> |
| 312 | + <script src="gitbook/jsrepl/jsrepl.js" id="jsrepl-script"></script> |
| 313 | + <script src="gitbook/app.js"></script> |
| 314 | + |
| 315 | + |
| 316 | + |
| 317 | + <script src="gitbook/plugins/gitbook-plugin-mixpanel/plugin.js"></script> |
| 318 | + |
| 319 | + |
| 320 | + |
| 321 | + <script src="http://cdn.mathjax.org/mathjax/2.0-latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script> |
| 322 | + |
| 323 | + |
| 324 | + |
| 325 | + <script src="gitbook/plugins/gitbook-plugin-mathjax/plugin.js"></script> |
| 326 | + |
| 327 | + |
| 328 | +<script> |
| 329 | +require(["gitbook"], function(gitbook) { |
| 330 | + var config = {}; |
| 331 | + gitbook.start(config); |
| 332 | +}); |
| 333 | +</script> |
| 334 | + |
| 335 | + |
| 336 | + </body> |
| 337 | + |
| 338 | +</html> |
0 commit comments