-
Notifications
You must be signed in to change notification settings - Fork 13
/
Copy pathchapter05.html
305 lines (177 loc) · 13.5 KB
/
chapter05.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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
<!DOCTYPE HTML>
<html lang="en-US" manifest="./manifest.appcache">
<head prefix="og: http://ogp.me/ns# book: http://ogp.me/ns/book#">
<meta charset="UTF-8">
<title>绑定 | Ruby中的元编程</title>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<meta name="robots" content="index, follow">
<meta name="author" content="">
<meta name="description" content=" 本系列翻译自Ruby Metaprogramming站点上的课程笔记,并加入了我(DeathKing)的一些个人演绎、资料补充等。希望对大家有所帮助。">
<meta name="keywords" content="gitbook,github" >
<meta name="generator" content="www.gitbook.io">
<link rel="next" href="./chapter06.html" />
<link rel="prev" href="./chapter04.html" />
<meta property="og:title" content="绑定 | Ruby中的元编程">
<meta property="og:site_name" content="Ruby中的元编程">
<meta property="og:type" content="book">
<meta property="og:locale" content="en_US">
<meta property="book:author" content="https://github.com/">
<meta property="book:tag" content="GitBook">
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<link rel="shortcut icon" href="gitbook/images/favicon.ico" type="image/x-icon">
</head>
<body>
<link rel="stylesheet" href="gitbook/style.css">
<div class="book" data-level="5" data-basepath="." data-revision="1401444078312">
<div class="book-header">
<!-- Actions Left -->
<a href="#" class="btn pull-left toggle-summary" aria-label="Toggle summary"><i class="fa fa-align-justify"></i></a>
<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>
<a href="#" class="btn pull-left toggle-search" aria-label="Toggle search"><i class="fa fa-search"></i></a>
<span id="font-settings-wrapper">
<a href="#" class="btn pull-left toggle-font-settings" aria-label="Toggle font settings"><i class="fa fa-font"></i>
</a>
<div class="dropdown-menu font-settings">
<div class="dropdown-caret">
<span class="caret-outer"></span>
<span class="caret-inner"></span>
</div>
<div class="btn-group btn-block">
<button id="reduce-font-size" class="btn btn-default">A</button>
<button id="enlarge-font-size" class="btn btn-default">A</button>
</div>
<ul class="list-group font-family-list">
<li class="list-group-item" data-font="0">Serif</li>
<li class="list-group-item" data-font="1">Sans</li>
</ul>
<div class="btn-group btn-group-xs btn-block color-theme-list">
<button type="button" class="btn btn-default" id="color-theme-preview-0" data-theme="0">White</button>
<button type="button" class="btn btn-default" id="color-theme-preview-1" data-theme="1">Sepia</button>
<button type="button" class="btn btn-default" id="color-theme-preview-2" data-theme="2">Night</button>
</div>
</div>
</span>
<!-- Actions Right -->
<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>
<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>
<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>
<!-- Title -->
<h1>
<i class="fa fa-spinner fa-spin"></i>
<a href="./" >Ruby中的元编程</a>
</h1>
</div>
<div class="book-summary">
<div class="book-search">
<input type="text" placeholder="Search" class="form-control" />
</div>
<ul class="summary">
<li data-level="0" data-path="index.html">
<a href="./"><i class="fa fa-check"></i> Introduction</a>
</li>
<li class="chapter " data-level="1" data-path="chapter01.html">
<a href="./chapter01.html">
<i class="fa fa-check"></i> <b>1.</b> 前言
</a>
</li>
<li class="chapter " data-level="2" data-path="chapter02.html">
<a href="./chapter02.html">
<i class="fa fa-check"></i> <b>2.</b> 实例变量、方法、类
</a>
</li>
<li class="chapter " data-level="3" data-path="chapter03.html">
<a href="./chapter03.html">
<i class="fa fa-check"></i> <b>3.</b> 方法的调用
</a>
</li>
<li class="chapter " data-level="4" data-path="chapter04.html">
<a href="./chapter04.html">
<i class="fa fa-check"></i> <b>4.</b> 实用元编程方法
</a>
</li>
<li class="chapter " data-level="5" data-path="chapter05.html">
<a href="./chapter05.html">
<i class="fa fa-check"></i> <b>5.</b> 绑定
</a>
</li>
<li class="chapter " data-level="6" data-path="chapter06.html">
<a href="./chapter06.html">
<i class="fa fa-check"></i> <b>6.</b> 块和绑定
</a>
</li>
<li class="chapter " data-level="7" data-path="chapter07.html">
<a href="./chapter07.html">
<i class="fa fa-check"></i> <b>7.</b> 元编程实战
</a>
</li>
<li class="chapter " data-level="8" data-path="chapter08.html">
<a href="./chapter08.html">
<i class="fa fa-check"></i> <b>8.</b> 结语
</a>
</li>
<li class="divider"></li>
<li>
<a href="http://www.gitbook.io/" target="blank" class="gitbook-link">Generated using GitBook</a>
</li>
</ul>
</div>
<div class="book-body">
<div class="body-inner">
<div class="page-wrapper" tabindex="-1">
<div class="book-progress">
<div class="bar">
<div class="inner" style="width: 62.5%;min-width: 50%;"></div>
</div>
<div class="chapters">
<a href="./index.html" title="Introduction" class="chapter done new-chapter" data-progress="0" style="left: 0%;"></a>
<a href="./chapter01.html" title="前言" class="chapter done new-chapter" data-progress="1" style="left: 12.5%;"></a>
<a href="./chapter02.html" title="实例变量、方法、类" class="chapter done new-chapter" data-progress="2" style="left: 25%;"></a>
<a href="./chapter03.html" title="方法的调用" class="chapter done new-chapter" data-progress="3" style="left: 37.5%;"></a>
<a href="./chapter04.html" title="实用元编程方法" class="chapter done new-chapter" data-progress="4" style="left: 50%;"></a>
<a href="./chapter05.html" title="绑定" class="chapter done new-chapter" data-progress="5" style="left: 62.5%;"></a>
<a href="./chapter06.html" title="块和绑定" class="chapter new-chapter" data-progress="6" style="left: 75%;"></a>
<a href="./chapter07.html" title="元编程实战" class="chapter new-chapter" data-progress="7" style="left: 87.5%;"></a>
<a href="./chapter08.html" title="结语" class="chapter new-chapter" data-progress="8" style="left: 100%;"></a>
</div>
</div>
<div class="page-inner">
<section class="normal" id="section-gitbook_9">
<h1 id="-">绑定</h1>
<p> 诸如本地变量、实例变量、<code>self</code>一类的实体……或者说所有于对象绑定的名称。我们把他们称为<strong>绑定(bindings)</strong>。</p>
<p> 下面内容摘自紫苏的博客,<a href="http://szsu.wordpress.com/2010/09/04/binding/" target="_blank">该文</a>对我们的讨论很有意义。</p>
<p> 在计算机科学中,<strong>“绑定”(Binding)</strong>一词是指一个更复杂、更大型的物件的引用的创建。例如当我们编写了一个函数,这个函数名就绑定了该函数本体,我们可以通过函数名来引用并调用该函数,这被称为名称绑定;又如当Ruby通过API去调用了C语言写的库函数时,这就是一个语言绑定;再如面向对象语言中的方法调度<code>obj.method</code>,这也是一个名称绑定,它会根据接收者<code>obj</code>具体的对象类型来确定应该引用哪个对象类型的<code>method</code>方法,而如果<code>obj</code>在编译时就能确定,那便可称之为<strong>静态绑定(早绑定)</strong>,早期的静态类型语言(如C)使用的是早绑定;如果obj在运行时才能确定,那便可称为<strong>动态绑定(迟绑定)</strong>,动态类型语言(如Ruby)使用的是迟绑定,而有些语言则同时支持早绑定和迟绑定,如C++的虚函数使用迟绑定,普通函数则使用早绑定。</p>
<p> 在Ruby中,<code>Kernel</code>有一个方法<code>binding</code>,它返回一个Binding类型的对象。这个<code>Binding</code>对象就是我们这里说的绑定,它封装了当前执行上下文中的所有绑定(变量、方法、语句块、<code>self</code>的名称绑定),而这些绑定直接决定了面向对象语言中的执行环境。比如,当我们调用<code>p</code>时,实际上是进行了<code>self</code>和<code>p</code>的绑定,而<code>p</code>具体是哪个方法,是由<code>self</code>的类型来决定的,如果我们在顶层,而<code>Kernel#p</code>又没有被重写,那<code>p</code>就是一个用来显示对象细节的方法。可以说有了一个绑定的列表,我们就有了一个完整的面向对象上下文的拷贝,就好比上帝在12分37秒复制了一份世界,而这个世界与原本世界的环境一模一样,既有这朵花,又有那株草。Ruby的Binding对象的概念和 Continuation有共通之处,但Continuation主要用于实际堆、栈内存的环境跳转,而Binding则比较高层。</p>
<p> 这个Binding对象有什么用?主要是用于<code>eval</code>这个函数。<code>eval</code>的第一个参数是需要<code>eval</code>的一段脚本字符串,而第二个可选参数则接受一个<code>Binding</code>对象。当指定了<code>Binding</code>时,<code>eval</code>会在传递给它的<code>Binding</code>所封装的执行环境里执行脚本,否则是在调用者的执行环境里执行。我们可以通过这个机制来进行一些不同上下文之间的通信,或者是在一个上下文即将被销毁之前保存该上下文环境以留他用,如:</p>
<pre><code class="lang-ruby"><span class="hljs-function"><span class="hljs-keyword">def</span> </span>foo
bar = <span class="hljs-string">'baz'</span>
<span class="hljs-keyword">return</span> binding
<span class="hljs-keyword">end</span>
eval(<span class="hljs-string">'p bar'</span>, foo)
</code></pre>
<p> 这里我们通过<code>foo</code>返回的<code>Binding</code>获取到了局部上下文销毁前的局部变量<code>bar</code>的值,而在不使用<code>binding</code>的情况下,局部变量<code>bar</code>在<code>foo</code>外层是不可见的。</p>
<p> 最后,Ruby有一个预定义的常量:<code>TOPLEVEL_BINDING</code>,它指向一个封装了顶层绑定的对象,通过它我们可以在其它上下文中通过<code>eval</code>在顶层上下文环境中执行脚本。</p>
</section>
</div>
</div>
</div>
<a href="./chapter04.html" class="navigation navigation-prev " aria-label="Previous page: 实用元编程方法"><i class="fa fa-angle-left"></i></a>
<a href="./chapter06.html" class="navigation navigation-next " aria-label="Next page: 块和绑定"><i class="fa fa-angle-right"></i></a>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.1.3/ace.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.1.3/mode-javascript.js"></script>
<script src="gitbook/jsrepl/jsrepl.js" id="jsrepl-script"></script>
<script src="gitbook/app.js"></script>
<script src="gitbook/plugins/gitbook-plugin-mixpanel/plugin.js"></script>
<script src="http://cdn.mathjax.org/mathjax/2.0-latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script src="gitbook/plugins/gitbook-plugin-mathjax/plugin.js"></script>
<script>
require(["gitbook"], function(gitbook) {
var config = {};
gitbook.start(config);
});
</script>
</body>
</html>