OSDN Git Service

タグを打ち忘れていたついでに、html版ドキュメントを追加しました。
[ring-lang-081/ring.git] / docs / ja-jp / build / html / _sources / scope.txt
1 .. index:: 
2         single: スコープ規則; はじめに
3
4 ========================
5 変数と属性のスコープ規則
6 ========================
7
8 Ring のスコープ規則と変数の検出方法、および名前衝突の解説、さらに解決方法と回避方法を学びます。
9
10 この情報は Ring で大規模アプリケーションの開発をはじめるときに重要です。
11
12 アプリケーションには下記が使用されています。
13
14 * グローバル変数 (使用を避けることに努めてください)
15
16 * クラス (オブジェクト指向)
17
18 * 括弧 { } によるオブジェクトのアクセス
19
20 * 宣言型プログラミング
21
22 * 自然言語プログラミング
23
24 .. index:: 
25         pair: スコープ規則; 三種類のスコープ
26
27 三種類のスコープ
28 ================
29
30 Ring には三種類のスコープがあります。
31
32 (1) パブリックスコープとグローバルスコープ - 各変数はステートメント部で定義されます (関数とクラスの前)
33
34 (2) オブジェクトスコープ - オブジェクトの内側にあるとき (クラスのメソッドの内側または { } の使用によるオブジェクトへのアクセス)
35
36 (3) ローカルスコープ - 関数とメソッドに関連付けられています
37
38 .. index:: 
39         pair: スコープ規則; 変数の定義と変数へのアクセス
40
41 変数の定義と変数へのアクセス
42 ============================
43
44 (1) Ring はレキシカルスコープを使用しています。つまり、変数のスコープは変数を定義した場所により決定します。
45
46 (2) { } 括弧内でのオブジェクトのアクセス時、現在有効なオブジェクトのスコープを対象となるオブジェクトのスコープへ変更します。今まで通り、グローバルスコープとローカルスコープへアクセスできます。
47
48 (3) 'Class' キーワードとクラス名末尾に、変数名の定義を記述したとしても、今まで通りグローバルスコープへアクセスできます。
49
50 この範囲 (クラスの範囲 - クラス名の後、およびメソッドの前) にあるものは、
51
52         * グローバルスコープ ----> グローバルスコープ
53         * オブジェクトスコープ ----> オブジェクトスコープ
54         * ローカルスコープ  ----> オブジェクトスコープ
55
56 .. note:: クラスの範囲にあるローカルスコープからでも、この範囲のオブジェクトスコープを指すため、入れ子の括弧は使用可能でありローカルスコープからクラスのオブジェクトスコープへのアクセスができます。
57
58 .. tip :: この範囲での定義によりウィンドウとコントロールの属性を作成できます。
59         
60 .. tip :: クラスの範囲にてオブジェクトの作成、および括弧 { } でオブジェクトへアクセスした後に、括弧の内側で Self.属性 を使うとクラスを使えます (アクセスしようとしているオブジェクトではありません)。この理由はローカルスコープからクラスを呼び出すことができるからです。
61
62 (4) 関数の仮引数は、自動的にローカルスコープへ定義されます。
63
64 .. index:: 
65         pair: スコープ規則; Ring による変数の検出方法
66
67 Ring による変数の検出方法
68 =========================
69
70 1 - 最初にローカルスコープを検索
71
72 * 見つからない!
73
74 2 - オブジェクトスコープの検索
75
76 * 見つからない!
77
78 3 - パブリックスコープの検索
79
80 * 見つからない ----> ランタイムエラー
81
82 * 見つかった ----> 次回の検索を回避するために、最適化できるかどうか確認します (性能改善のためのポインタとキャッシュ)。
83
84 .. index:: 
85         pair: スコープ規則; オブジェクト.属性の用法
86
87 オブジェクト.属性の用法
88 ===========================
89
90 オブジェクト.属性 を使うときはオブジェクト属性に限り検索を行います。
91
92 つまり、ローカルスコープまたはグローバルスコープのオブジェクト属性では検索は行いません。
93
94 .. note:: Self.属性を使うときは属性を検索する前に Self の検索を最初に行います。
95
96
97 .. index:: 
98         pair: スコープ規則; Self オブジェクト
99
100 Self オブジェクト
101 =================
102
103 Selft オブジェクトは現在のオブジェクトを参照するためにクラスのメソッドから使えます!
104
105 クラスのメソッドの内側であり Self を使うときは、このクラスから作成されるオブジェクトを意味します。
106
107 クラスのメソッドの内側で括弧 { } を使うと、現在のオブジェクトのスコープを変更します。
108 また、 Self でオブジェクトへアクセスするときに、括弧の内側にある参照を変更します。
109
110 クラスの範囲 (クラス名の後、およびメソッドの前) の内側はオブジェクトスコープ、
111 およびローカルスコープからオブジェクトへのアクセスすることもできます。
112 この範囲で Self を使うと、常にクラスのオブジェクトへ参照されます。
113 オブジェクトのスコープの変更で括弧を使用後に、括弧の内側で Self を使用した場合でも、
114 クラスの範囲内にあるため、 Self はクラスオブジェクトへの参照になります (既に括弧でアクセスしているオブジェクトではありません)。
115
116 * グローバルスコープ   ---> グローバルスコープ
117 * オブジェクトスコープ ---> オブジェクトスコープ
118 * ローカルスコープ     ---> オブジェクトスコープ
119
120 括弧を使うとオブジェクトのスコープのみ変更されます。
121 Ring は変数を検索するときに、ローカルスコープを最初に検索するためクラスの内側にある Self を検出します。
122
123 .. index:: 
124         pair: スコープ規則; Ring における変数と属性の定義方法
125
126
127 Ring における変数と属性の定義方法
128 =================================
129
130 Ring は代入操作で変数名を使用します。
131
132 1 - 変数名で検索
133
134 2 - 見つからない ---> ランタイムエラーの回避と現在のスコープへ変数を定義します。
135
136 3 - 見つかった ---> 変数を使用しますが現在のスコープへ変数を一切定義しません。
137
138 * グローバルの範囲 (関数またはクラスの前) において現在のスコープはグローバルスコープになります。
139
140 * クラスの範囲 (クラス名の後、およびメソッドの前) において現在のスコープはオブジェクトの属性になります。
141
142 * 関数とメソッドにおける現在のスコープはローカルスコープになります。
143
144 .. index:: 
145         pair: スコープ規則; クラス属性とグローバル変数の間での名前衝突
146
147
148 クラス属性とグローバル変数の間での名前衝突
149 ==========================================
150
151 この用例を参照してください:
152
153 .. code-block:: ring
154
155         name = "test"
156         o1 = new person
157         see o1
158
159         class person
160                 name
161                 address 
162                 phone
163
164 前述の用例ではグローバル変数 ‘name’ が
165 person クラスの内側にあります。
166
167 Ring は‘name’ 変数を使用するにとき検索処理の開始、
168 および検出します。
169
170 見つかった   --->  見つかったものを使用
171
172 見つからない --->  新しい属性の定義
173
174 しかし、変数名はグローバル変数であるため、検出後に使用されます!
175
176 属性名が存在しない! オブジェクトへ追加します。
177
178 解決方法① - Main 関数の使用
179
180 .. code-block:: ring
181
182         func main
183                 name = "test"
184                 o1 = new person
185                 see o1
186
187         class person
188                 name
189                 address 
190                 phone
191
192 解決方法② - $ などのグローバル変数名に特殊記号を使用
193
194 .. code-block:: ring
195
196         $name = "test"
197         o1 = new person
198         see o1
199
200         class person
201                 name
202                 address 
203                 phone
204
205 解決方法③ - AddAttribute() メソッドの使用
206
207 .. code-block:: ring
208
209         name = "test"
210         o1 = new person
211         see o1
212
213         class person
214                 AddAttribute(self,"name")
215                 address 
216                 phone
217
218 解決方法④ - 属性名の先頭に Self を使用
219
220 .. code-block:: ring
221
222         name = "test"
223         o1 = new person
224         see o1
225
226         class person
227                 self.name
228                 address 
229                 phone
230
231
232 この名前衝突に関する最善の解決方法は?
233
234 1 - グローバル変数で $ 記号を使用
235
236 2 - オプション扱い : グローバル変数の回避する、または Main 関数の使用
237
238 実際は両方とも実施します。
239
240 そのほかの解決方法
241
242 * 属性名の先頭に Self を使います。または AddAttribute() を使用します。
243
244 .. index:: 
245         pair: スコープ規則; クラス属性とローカル変数の間での名前衝突
246
247 クラス属性とローカル変数の間での名前衝突
248 ========================================
249
250 この名前衝突は、括弧でオブジェクトにアクセスするときに発生します。
251
252 用例:
253
254 .. code-block:: ring
255  
256         func main
257                 name = "nice"
258                 o1 = new person {name="mahmoud" address="Egypt"  phone = 000 }
259                 see o1
260
261         class person 
262                 name
263                 address
264                 phone
265
266 前述の用例にはローカル変数名があります。
267
268 この変数の値は、オブジェクトの属性ではなく“mahmoud”が設定されます。
269
270 解決方法① : Self の使用
271
272 .. code-block:: ring
273
274         func main
275                 name = "nice"
276                 o1 = new person {self.name="mahmoud" address="Egypt"  phone = 000 }
277                 see o1
278
279         class person 
280                 name
281                 address
282                 phone
283
284 解決方法② : ローカル変数名の変更
285
286 .. code-block:: ring
287
288         func main
289                 cName = "nice"
290                 o1 = new person {name="mahmoud" address="Egypt"  phone = 000 }
291                 see o1
292
293         class person 
294                 name
295                 address
296                 phone
297
298 解決方法③ : 括弧の変更およびドット演算子を使用
299
300 .. code-block:: ring
301
302         func main
303                 name = "nice"
304                 o1 = new person 
305                 o1.name ="mahmoud" 
306                 o1.address ="Egypt"  
307                 o1.phone = 000 
308                 see o1
309
310         class person 
311                 name
312                 address
313                 phone
314
315
316 .. index:: 
317         pair: スコープ規則; 括弧によるクラスのメソッドの内側にあるオブジェクトへのアクセス方法
318
319 括弧によるクラスのメソッドの内側にあるオブジェクトへのアクセス方法
320 ======================================================================
321
322 クラスのメソッドの内側では三種類のスコープ (ローカルスコープ、オブジェクトスコープとグローバルスコープ) があることを思い出してください。
323 これはオブジェクト属性とメソッドへアクセス可能であると期待しており、
324 括弧でオブジェクトの属性とメソッドへアクセスするまでは本当です。
325 この場合は、オブジェクトのスコープが別のオブジェクトへ切り替えられるためです。
326
327 .. code-block:: ring
328
329         new point { test() }
330
331         class point
332                 x=10 y=20
333                 func test
334                         see x + nl + y + nl # 正常に動作します。
335                         myobj = new otherclass {
336                                 see name + nl
337                                 see x + nl + y + nl # エラー!
338                         }
339
340         class otherclass
341                 name = "test"
342
343 実行結果:
344
345 .. code-block:: none
346
347         10
348         20
349         test
350
351         Line 8 Error (R24) : Using uninitialized variable : x
352         In method test() in file methodbraceerror.ring
353         called from line 5  in file methodbraceerror.ring
354
355 さて、前述の問題の解決方法は?
356
357 解決方法 (1) : 括弧の外側にあるクラスの属性へアクセスするためのコードを記述する。
358
359 .. code-block:: ring
360
361         new point { test() }
362
363         class point
364                 x=10 y=20
365                 func test
366                         see x + nl + y + nl # 正常に動作します。
367                         myobj = new otherclass {
368                                 see name + nl
369                         }
370                         see x + nl + y + nl # 括弧の外側 - 正常に動作します。
371
372
373         class otherclass
374                 name = "test"
375
376
377 実行結果:
378
379 .. code-block:: none
380
381         10
382         20
383         test
384         10
385         20
386
387
388 解決方法② : 括弧を使用しない
389
390 .. code-block:: ring
391
392         new point { test() }
393
394         class point
395                 x=10 y=20
396                 func test
397                         see x + nl + y + nl  
398                         myobj = new otherclass 
399                         see myobj.name
400                         see x + nl + y + nl                     
401
402         class otherclass
403                 name = "test"
404
405
406 解決方法③ : Self オブジェクトのコピー
407
408 この解決方法は、括弧でクラス属性へアクセスしたいときに使用します (読み取り)。
409
410 .. code-block:: ring
411
412         new point { test() }
413
414         class point
415                 x=10 y=20
416                 func test
417                         oSelf = self
418                         see x + nl + y + nl  
419                         myobj = new otherclass {
420                                 see name + nl
421                                 see oself.x + nl + oself.y + nl  
422                         }
423
424         class otherclass
425                 name = "test"
426
427 実行結果:
428
429 .. code-block:: none
430
431         10
432         20
433         test
434         10
435         20
436
437 この行を参照してください
438
439 .. code-block:: ring
440
441         oself = self
442
443 前行の問題はオブジェクトの新しいコピーあることです。
444 この理由は Ring の代入演算子はリストと値によるオブジェクト (参照ではない) はコピーしないからです。
445
446 新しいオブジェクトへアクセスする場合は問題はありません (読み取り)。
447
448 オブジェクトの属性を変更した場合は問題があります (そのためコピーを変更します!)
449
450 .. note:: 括弧はコピーを行うときに再度使えます。
451
452 .. code-block:: ring
453
454         new point { test() }
455
456         class point
457                 x=10 y=20
458                 func test
459                         oSelf = self
460                         see x + nl + y + nl  
461                         myobj = new otherclass {
462                                 see name + nl
463                                 oSelf {
464                                         see x + nl + y + nl
465                                 }
466                         }
467
468         class otherclass
469                 name = "test"
470
471 GUI アプリケーションでは、様々なメソッドからコントロールへアクセス可能な属性として、
472 Window オブジェクトがあるクラスを作成します。
473 括弧でメソッドの内側にあるオブジェクトへアクセスするときは、前述の情報を思い出してください。
474 この場合は、オブジェクトとの属性へアクセスできないため Self オブジェクトをコピーした場合は、コピー先での作業となります。
475 新しいコントロールの作成は、コピーと関連付けられていますがアクセスはできません。
476
477
478 .. index:: 
479         pair: スコープ規則; クラスのメソッド内にある括弧からクラスの属性にアクセスするには
480
481
482 クラスのメソッド内にある括弧からクラスの属性にアクセスするには
483 ==============================================================
484
485 クラスのメソッドからクラスの属性へ直接アクセスするために、属性やメソッド名の先頭に Self による参照を選択する方法があります。
486 クラスのメソッド内で括弧 { } を使うと、有効なオブジェクトのスコープを変更することになり、
487 クラスの属性へ直接アクセスするのを防ぎます。また Self の使用は、括弧でアクセスするオブジェクトを変更できるため Self による参照は効果がありません。
488
489 この場合、属性を読み取りたい場合は、括弧の使用前に
490 Self オブジェクトを必ずコピーしてください。
491 また、括弧の後に、オブジェクトの属性からローカル変数へコピーしたい場合は、必ず属性を修正してください。
492
493 この場合は、括弧の内側にある属性の読み取り、または変更をしたいときに発生します。
494
495 .. code-block:: ring
496
497         Class MyApp
498
499                 oCon   # 属性
500
501                 # こちらへコードを記述してください。
502
503                 Func OpenDatabase
504                         # こちらへコードを記述してください。
505                         new QSqlDatabase() {
506                                 oCon = addDatabase("QSQLITE") {
507                                         setDatabaseName("weighthistory.db")
508                                         open()
509                                 }
510                         }       
511                         self.oCon = oCon 
512                         # こちらへコードを記述してください。
513
514 前述の用例で connection オブジェクトを作成して oCon 属性の内側で保存したいとします。
515
516 このオブジェクトは QSQLDatabase() オブジェクトのアクセス後に使用する addDatabase() メソッドからの出力です。
517
518 括弧の内側では MyApp クラスから作成したオブジェクトによる Self 参照の使用はできません。
519 ここで Self 参照を使用することは、括弧でオブジェクトをアクセスすることになるからです。
520
521 ローカル変数 oCon を作成してから、括弧の後に oCon 属性を変数へコピーすることにより、
522 前述の問題を解決しました。
523
524 このコードは別の解決方法です。
525
526 .. code-block:: ring
527
528         Class MyApp
529
530                 oCon   # 属性
531
532                 # こちらへコードを記述してください。
533
534                 Func OpenDatabase
535                         # こちらへコードを記述してください。
536                         oCon = new QSqlDatabase()
537                         oCon = oCon.addDatabase("QSQLITE") {
538                                 setDatabaseName("weighthistory.db")
539                                 Open()  
540                         }
541                 # こちらへコードを記述してください。
542
543
544 このコードは優れた解決方法です。
545
546 .. code-block:: ring
547
548         Class MyApp
549
550                 oCon   # 属性
551
552                 # こちらへコードを記述してください。
553
554                 Func OpenDatabase
555                         # こちらへコードを記述してください。
556                         new QSqlDatabase() {
557                                 this.oCon = addDatabase("QSQLITE") {
558                                         setDatabaseName("weighthistory.db")
559                                         Open()  
560                                 }
561                         }
562                         # こちらへコードを記述してください。   
563
564 .. note:: 括弧の内側でクラスの属性 (oCon) へアクセスするために This.属性 を使用しています。
565
566
567 .. index:: 
568         pair: スコープ規則; GUI アプリケーションのウィンドウごとにクラスを作成するには
569
570 GUI アプリケーションのウィンドウごとにクラスを作成するには
571 ==========================================================
572
573 ウィンドウ用のクラスを作成するための優れた方法は、クラス名の直後にウィンドウを定義することです。
574
575 ウィンドウをコントロールの定義に関する問題は発生せずに、入れ子の括弧を使えます。
576 そして、属性はメソッドからアクセスできます。
577
578 用例:
579
580 .. code-block:: ring
581
582         Load "guilib.ring"
583
584         new qApp 
585         {
586                 $ObjectName = "oFirstWindow"
587                 oFirstWindow = new FirstWindow
588
589                 $ObjectName = "oSecondWindow"
590                 oSecondWindow = new SecondWindow
591
592                 exec()
593         }
594
595         Class FirstWindow
596
597                 win = new qWidget() {
598                         setgeometry(0,50,300,200)
599                         setWindowTitle("First Window")
600                         label1 = new qLabel(win)
601                         {
602                                 setgeometry(10,10,300,30)
603                                 setText("0")
604                         }
605                         btn1 = new qPushButton(win)
606                         {
607                                 move(100,100)
608                                 setText("Increment")
609                                 setClickEvent($ObjectName+".increment()")
610                         }
611                         show()
612                 }       
613
614                 Func Increment
615                         label1 {
616                                 setText( "" + ( 0 + text() + 1 ) )
617                         }
618
619
620         Class SecondWindow
621
622                 win = new qWidget() {
623                         setgeometry(400,50,300,200)
624                         setWindowTitle("Second Window")
625                         label1 = new qLabel(win)
626                         {
627                                 setgeometry(10,10,300,30)
628                                 setText("0")
629                         }
630                         btn1 = new qPushButton(win)
631                         {
632                                 move(100,100)
633                                 setText("Decrement")
634                                 setClickEvent($ObjectName+".decrement()")
635                         }
636                         show()
637                 }       
638
639                 Func Decrement
640                         label1 {
641                                 setText( "" + ( 0 + text() - 1 ) )
642                         }
643
644 .. index:: 
645         pair: スコープ規則; クラス範囲にある括弧内の Self と Self 間との名前衝突
646
647 クラス範囲にある括弧内の Self と Self 間との名前衝突
648 ====================================================
649
650 クラスの領域 (クラス名の後、そしてメソッドの前) で属性を定義します。
651
652 この領域では、グローバルスコープへアクセスできます。そして、ローカルスコープはオブジェクトスコープを指します。
653
654 三種類のスコープ
655
656 * グローバルスコープ   ---> グローバルスコープ
657 * オブジェクトスコープ ---> オブジェクトスコープ
658 * ローカルスコープ     ---> オブジェクトスコープ
659
660 三種類のスコープ
661
662 .. code-block:: ring
663
664         New Account {
665                 see aFriends
666         }
667
668         Class Account
669                 name = "Mahmoud"
670                 aFriends = []
671                 aFriends + new Friend { 
672                         name = "Gal" 
673                 }
674                 aFriends + new Friend { 
675                         name = "Bert" 
676                 }
677         
678         Class Friend
679                 name
680
681 実行結果:
682
683 .. code-block:: none
684
685         name: NULL
686         name: NULL
687
688 前述の用例における問題は account クラスには “name” 属性があり、 
689 Friend クラスにも同名属性 “name” があります。
690
691 括弧内で self.name を使うと前述の用例と同じ結果になります!
692
693 .. code-block:: ring
694
695         New Account {
696                 see aFriends
697         }
698
699         Class Account
700                 name = "Mahmoud"
701                 aFriends = []
702                 aFriends + new Friend { 
703                         self.name = "Gal" 
704                 }
705                 aFriends + new Friend { 
706                         self.name = "Bert" 
707                 }
708         
709         Class Friend
710                 name
711
712 この名前衝突に関して、括弧の内側で self.name でも解決しない理由は?
713
714 このようなクラスの範囲になるからです。
715
716 * グローバルスコープ   ---> グローバルスコープ
717 * オブジェクトスコープ ---> オブジェクトスコープ (Account クラス)
718 * ローカルスコープ     ---> ローカルスコープ (Account クラス)
719
720 括弧を使うとき、オブジェクトのスコープは変更されるため、このようになります。
721
722 * グローバルスコープ   ---> グローバルスコープ
723 * オブジェクトスコープ ---> オブジェクトスコープ (Friend クラス)
724 * ローカルスコープ     ---> ローカルスコープ (Account クラス)
725
726 Ring では、ローカルスコープを最初に検索するため、 self.name を使うときは Account クラスを使用します。
727
728 様々な解決方法があります。
729
730 解決方法① : リストによるオブジェクトへのアクセス
731
732 .. code-block:: ring
733
734         New Account {
735                 see aFriends
736         }
737
738         Class Account
739                 name = "Mahmoud"
740                 aFriends = []
741                 aFriends + new Friend
742                 aFriends[len(aFriends)] { 
743                         aFriends[len(aFriends)].name = "Gal" 
744                 }
745                 aFriends + new Friend 
746                 aFriends[len(aFriends)] { 
747                         aFriends[len(aFriends)].name = "Bert" 
748                 }
749         
750         Class Friend
751                 name
752
753 解決方法② : name 属性を設定するために friend クラスでメソッドを作成
754
755 .. code-block:: ring
756
757         New Account {
758                 see aFriends
759         }
760
761         Class Account
762                 name = "Mahmoud"
763                 aFriends = []
764                 aFriends + new Friend { 
765                         setname("Gal")
766                 }
767                 aFriends + new Friend { 
768                         setname("Bert")
769                 }
770         
771         Class Friend
772                 name
773                 func setname cName
774                         name = cName
775
776 解決方法③ : 属性を設定するために account クラスでメソッドを作成
777
778 .. code-block:: ring
779
780         New Account {
781                 see aFriends
782         }
783
784         Class Account
785                 name = "Mahmoud"
786                 aFriends = []
787                 friend("Gal")
788                 friend("Bert")
789
790                 func friend cName
791                         aFriends + new Friend { 
792                                 name = cName
793                         }
794         
795         Class Friend
796                 name
797
798 解決方法④ : 宣言型プログラミング
799
800 .. code-block:: ring
801
802         New Account {
803                 name = "mahmoud"
804                 friend {
805                         name = "Gal"
806                 }
807                 friend {
808                         name = "Bert"
809                 }
810                 see aFriends
811         }
812
813         Class Account
814                 name 
815                 aFriends = []
816                 friend
817                 func getfriend
818                         aFriends + new Friend
819                         return aFriends[len(aFriends)]
820         
821         Class Friend
822                 name
823
824 実行結果:
825
826 .. code-block:: none
827
828         name: Gal
829         name: Bert
830
831 .. index:: 
832         pair: スコープ規則; 括弧による現在のオブジェクトスコープの除外方法
833
834
835 括弧による現在のオブジェクトスコープの除外方法
836 ==================================================
837
838 括弧から現在のオブジェクトスコープを別のオブジェクトスコープへ変更します。
839 クラス属性の変更、および同名変数の使わずに処理できます。
840
841 .. code-block:: ring
842
843         new point {x=10 y=20 z=30 start() }
844         class point x y z
845                 func start
846                         see self # x y z の値を表示 (10,20,30)
847                         new Local {
848                                 x = 100
849                                 y = 200
850                                 z = 300
851                         }
852                         see self # x y z の値を表示 (10,20,30)
853                         see x + nl # 100 の表示
854                         see y + nl # 200 の表示
855                         see z + nl # 300 の表示
856                         Self {  # 利点なし - ローカルスコープの最初の検索で完了します。
857                                 see x + nl # 100 の表示
858                                 see y + nl # 200 の表示
859                                 see z + nl # 300 の表示
860                         }
861                         see self.x + nl # 10 の表示
862                         see self.y + nl # 20 の表示
863                         see self.z + nl # 30 の表示
864
865         class Local
866         
867 実行結果:
868
869 .. code-block:: none
870
871         x: 10.000000
872         y: 20.000000
873         z: 30.000000
874         x: 10.000000
875         y: 20.000000
876         z: 30.000000
877         100
878         200
879         300
880         100
881         200
882         300
883         10
884         20
885         30
886         
887
888
889 .. index:: 
890         pair: スコープ規則; For ループでローカルスコープを使用
891
892 For ループでローカルスコープを使用
893 ==================================
894
895 Ring 1.8 より、 For ループでの新規識別子 (変数) を定義するときは、ローカルスコープで定義します。
896
897 用例:
898
899 .. code-block:: ring
900
901         x = 10
902         ? x             # 10 の表示
903         test1()
904         ? x             # 10 の表示
905         test2()
906         ? x             # 10 の表示
907
908         func test1
909                 for x = 1 to 5
910                 next
911                 ? x     # 6 の表示
912
913         func test2
914                 list = 1:5
915                 for x in list
916                 next
917                 ? x     # NULL の表示 ("For In" ループでは、ループ完了後に参照を破棄します)
918
919 実行結果:
920
921 .. code-block:: ring
922
923         10
924         6
925         10
926         NULL
927         10      
928         
929
930
931 .. index:: 
932         pair: スコープ規則; スコープ規則のまとめ
933
934
935 スコープ規則のまとめ
936 ======================
937
938 最初に次のことを覚えておいてください。
939
940 1 - 各種プログラミング言語には言語の目的に基づいたスコープ規則があります。
941
942 2 - 小規模プログラミングと大規模プログラミングは異なります。
943
944 3 - あるプログラミング言語は小規模プログラミング用に設計されていますが、それ以外は大規模プログラミング用に設計されています。
945
946 4 - プログラミングで、スコープへのアクセスが複数ある場合があります。 - 正確に管理されていない場合は問題になります。
947
948 5 - 可視スコープの個数を削減することで、さらなる安全性を保ち続けることができます。
949
950 6 - あるプログラミング言語では、ある方法でスコープの管理を強制しており、それ以外の方法はありません!
951
952 Ring では
953
954 1 - まず柔軟性、そして次に安全性を求めて設計された特別かつ「非常に単純明快」なスコープ規則があります
955
956 2 - Ring は小規模プログラミングと大規模プログラミングに対応するように設計されています。
957
958 3 - Ring にはプロジェクトの規模に基づいて選択可能な各種プログラミング・パラダイムがあります。ターゲットとなるプロジェクトで悪いパラダイムを選択した、または間違っているか一般的ではない方法によりパラダイムを使用するとエラーになります。
959
960 4 - Ring  には選択肢があります。グローバル変数の使用、または使用を避けることができます。特殊記号 $ の指定、または除去できます。オブジェクト指向を使用する、または手続き型の使用を継続できます。クラス範囲 (クラスの範囲 - クラス名の後、およびメソッドの前) で属性の使用、またはコードで属性を使えます。
961
962 5 - このスコープ規則をご確認になり、記載されていることについて考えた後に好きな方法を使用してください。
963
964 スコープ規則:
965
966 1 - プログラムのコードのすべての場所において最大三種類のスコープだけあります (ローカルスコープ、オブジェクトのスコープとグローバルスコープ)。
967
968 2 - Ring が変数を検索するとき、最初にローカルスコープを、次にオブジェクトのスコープを、そしてグローバルスコープを検索します。
969
970 3 - 手続き、またはメソッドは、括弧 { } でオブジェクトへのアクセス、および現在のオブジェクトのスコープをいつでも変更できます。
971
972 4 - クラスの範囲 (クラス名の後、およびメソッドの前) において、これはオブジェクトスコープでオブジェクトのスコープとローカルスコープの両方を指す特別な範囲です。すなわち、この範囲で定義する各変数は属性になるため、ローカル変数ではありません。
973
974 5 - 変数 (スコープとクラスの範囲)  の定義前に検索処理で変数が検出された場合は検出された変数を使用します。
975
976 6 - 関数とメソッドの仮引数は関数、またはメソッドへのローカル変数として自動的に定義されます。
977
978 7 - オブジェクト.属性 を使うとオブジェクト属性のみ検索します。
979
980 8 - Self.属性 を使うと先頭にある Self を最初に検索してから Self の属性を検索します。
981
982 9 - クラスの範囲 (クラス名の後、そしてメソッドの前) の内側にある Self 参照はクラスから作成されたオブジェクトのスコープを指します。
983
984 10 -メソッドの内側にある Self 参照は括弧による参照でオブジェクトへアクセスするときに変更されます。
985
986 11 - クラスの範囲 (クラス名の後、そしてメソッドの前) に変数名を直接記述すると、それらの使用または定義の意味となります。
987
988 12 - クラスの範囲で Self.属性 を使うと検索対象となるオブジェクトのスコープの個数を削減します (グローバルスコープとの名前衝突を回避します)。
989
990 これらの規則から名前衝突が何故発生するのか、そして回避するにはどうしたら良いかを理解できます。
991
992 名前衝突を避けるための簡単な助言として、スコープ規則を使用することが最良の方法です。
993
994 1 - グローバル変数の回避をしてください。
995
996 2 - Main 関数の使用 - これはグローバル変数の回避に有効です。
997
998 3 - グローバル変数を多用する場合は変数名の先頭に $ を使用してください。
999
1000 4 - クラスの範囲で三番目 ($ の使用) の助言を考慮しない場合は、属性を定義するときに self.属性 を使用します。
1001
1002 5 - オブジェクトのスコープを変更したくない場合は、オブジェクト { 属性 } と オブジェクト { メソッド() } の代わりに オブジェクト.属性 と オブジェクト.メソッド() を使用します。
1003
1004 6 - 入れ子の括弧をクラスで使用する場合 - この範囲で { } +  によりクラス属性へアクセスするために、オブジェクトのアクセス権がある場合はクラス範囲の使用に関して可能ならば考慮してください。
1005
1006 7 - クラスのメソッドの内側、および入れ子の括弧が使用されている場合は、括弧ごとにオブジェクトのスコープは変更されるため、直ちにクラスの属性へのアクセス権を失いますが、括弧 { } でローカルスコープの前後へアクセスできます。括弧からクラスの属性を読み取り、 または修正する場合は This.属性 を使用してください。この理由として ‘This’ を使用することは「このクラスからオブジェクトが作成される」ことを意味するのとは違い ‘Self’ (現在のスコープにあるオブジェクト) を意味します。
1007
1008 前述の要点を全て理解したならば、本章を会得したことになります。
1009