## 10.可變范圍
在上一節中我們已經了解了函數,而在之前我們已經了解了變量。 我認為現在是時候輸入變量范圍了。 在本章中,我們將探討在程序的特定部分中聲明變量時有價值的時間或長度。 讓我們從一個例子開始。 啟動你的文本編輯器,輸入下面的代碼( [variable_scope.rb](code/variable_scope.rb) )并執行它。
```rb
#!/usr/bin/ruby
# variable_scope_.rb
x = 5
def print_x
puts x
end
print_x
```
輸出量
```rb
variable_scope.rb:7:in `print_x': undefined local variable or method `x' for main:Object (NameError)
from variable_scope.rb:10
```
好吧,你得到一個錯誤。 看到你已經通過輸入`x = 5`聲明了一個變量。 在函數`print_x`中,你告訴 ruby 程序打印出變量 x,但會引發錯誤。 看一下輸出,它說`undefined local variable or method `x' for main:Object (NameError) from variable_scope.rb:10`,那么我們已經定義了`x`并在開始時將其分配為值 5,那么 Ruby 如何拋出錯誤? 好吧,我們在函數`print_x`之外定義了`x`,因此`x`內部沒有作用域,因此會出現錯誤。
優秀的程序員可以利用編程語言提供的優勢,并且足夠聰明,可以按其施加的規則和限制發揮作用。 對于新手來說,我們無法訪問我們在函數外部分配的變量似乎是一個真正的障礙,但是當你的程序成為成熟的程序員時,你會變相地實現它的祝福。
要了解更多信息,請在文本編輯器中鍵入以下程序(variable_scope_1.rb)并執行。
```rb
#!/usr/bin/ruby
# variable_scope_1.rb
x = 5
def print_x
x=3
puts x
end
print_x
puts x
```
Output
```rb
3
5
```
仔細看一下輸出。 首先在程序中聲明變量`x = 5`,然后在函數`print_x`中聲明變量`x = 3`。 注意,在函數`print_x`中聲明的變量與在函數外部聲明的變量不同。 接下來,我們調用函數`print_x`,該函數將輸出打印為 3,這是預期的結果,因為在`print_x`內部我們在`x = 3`之后編寫了`puts x`。 下一個語句是此處的英雄,(在函數外)我們在`print_x`之后寫了`puts x`,如果你希望打印 3,則你錯了。 這里`x`是我們在函數外部聲明的`x`,在這里它將被打印為 5。這意味著在函數內部聲明的變量在其外部沒有作用域。
要了解更多信息并說服函數內部聲明的變量在函數外部沒有作用域,我們將嘗試另一個程序。 在文本編輯器中輸入程序 [variable_scope_2.rb](code/variable_scope_2.rb) 并執行它。
```rb
#!/usr/bin/ruby
# variable_scope_2.rb
def print_variable
y = 3
puts y
end
print_variable
puts y
```
Output
```rb
3
variable_scope_2.rb:10: undefined local variable or method `y' for main:Object (NameError)
```
這是該程序的工作方式,或者我應該說這是該程序因拋出錯誤而無法工作的方式。 看一下函數`print_variable`,在其中我們使用語句`y = 3`聲明了一個名為`y`的變量,并告訴 ruby 解釋器使用語句`puts y`打印其值。 因此,在程序中,當我們調用`print_variable`時,將聲明`y`,并且其值 3 不會出現故障。 接下來,我們在函數`print_variable`之外說`puts y`,因為`y`僅在函數內聲明,所以在變量`y`之外不存在,并且從技術上講它沒有作用域,因此 Ruby 解釋器拋出 錯誤。 所以我們得到如下錯誤信息:
```rb
variable_scope_2.rb:10: undefined local variable or method `y' for main:Object (NameError)
```
* * *
Matz(Ruby 的創建者)似乎沒看過電影《回到未來》。 讓我們看看另一個證明時間旅行沒有內置的程序,在文本編輯器中輸入以下程序( [variable_scope_3.rb](code/variable_scope_3.rb) )并執行它。
```rb
#!/usr/bin/ruby
# variable_scope_3.rb
puts a # you can't access a variable that will be created in future
a = 10
```
Output
```rb
variable_scope_3.rb:4: undefined local variable or method `a' for main:Object (NameError)
```
如果你預期正確,程序將拋出錯誤。 我們已經在聲明`a`之前給了`puts a`。 Ruby 解釋器不會考慮將來聲明的內容,因此,在遇到`puts a`時,此時將不會聲明`a`,因此會引發錯誤。 換句話說,變量的作用域僅在聲明后才開始。
### 10.1。 全局變量
如果你不喜歡無法從函數外部訪問聲明的變量的想法,那么 Ruby 提供了一種方法。 有一些稱為全局變量的特殊變量,可以從任何地方訪問。 全局變量前面帶有美元($)符號。 要了解全局變量,請看一個示例。 在下面鍵入程序( [global_variables.rb](code/global_variables.rb) )并執行它。
```rb
#!/usr/bin/ruby
# global_variables.rb
$x = 5
def print_x
$x = 3
puts $x
end
print_x
puts $x
```
Output
```rb
3
3
```
成功運行它,讓我們看看它是如何工作的。 首先,我們聲明一個全局變量$ x 并將其分配給語句`$x = 5`中的值 5。 接下來,我們定義一個函數`print_x`,其中使用語句`$x = 3`將`$x`的值更改為 3,然后使用`puts $x`打印`$x`的值。 因此,顯然我們調用`print_x`,將得到的輸出為 3。接下來,在調用`print_x`之后的函數外部,我們將使用`puts $x`打印`$x`的值。 如果你認為它將打印出 5,那么你就錯了。 由于可以從任何位置訪問`$x`,因此我們將其稱為`print_x`,在`print_x`中,無論如何,我們都將`$x`的值更改為 3,即使在函數范圍之外,也將`$x`的值更改為 `$x`將被更改。
讓我們來看另一個示例,以更好地理解全局變量。 查看下面的示例( [global_variables_1.rb](code/global_variables_1.rb) ),在文本編輯器中鍵入并執行它
```rb
#!/usr/bin/ruby
# global_variables_1.rb
$x = 5
def print_x
puts $x
end
print_x
$x = 7
print_x
$x = 3
print_x
```
這是程序輸出的樣子
```rb
5
7
3
```
讓我們看看程序如何工作。 首先,我們聲明一個全局變量`$x`并使用`$x = 5`將其分配給值 5,然后定義一個名為`print_x`的函數,在其中我們只需使用`puts $x`語句打印出`$x`的值。 當我們調用第一個 print_x 語句時,`$x`的值為 5,因此將輸出 5。 接下來,在語句`$x = 7`中將`$x`的值更改為 7,然后調用`print_x`時,將打印現在為 7 的`$x`的值。 最后,使用`$x = 3`將`$x`設置為 3,當最后一次調用`print_x`時,將打印出 3 個。
該程序證明了可以從任何地方操作全局變量,并且可以從任何地方訪問這些操作值。 接下來出現一個問題,天氣全局變量和局部變量可以具有相同的名稱。 答案是肯定的。 這是因為全局變量以`$`符號開頭,而局部變量以字母或下劃線字符開頭,因此 ruby 可以清楚地區分它們之間的區別。 讓我們來看一個證明這一點的程序,閱讀,學習類型并執行下面給出的程序( [global_variables_2.rb](code/global_variables_2.rb) )。 完成操作后,我們將看到其工作原理。
```rb
#!/usr/bin/ruby
# global_variables_1.rb
$x = 5
x = 5
def print_x
$x = 3
x = 3
puts "In print_x"
puts "$x = "+$x.to_s
puts "x = "+x.to_s
end
print_x
puts "Outside print_x"
puts "$x = "+$x.to_s
puts "x = "+x.to_s
```
Output
```rb
In print_x
$x = 3
x = 3
Outside print_x
$x = 3
x = 5
```
在上面的程序中,我們在以下幾行中聲明兩個變量,一個是全局變量`$x`并將其分配給值 5,另一個是局部變量`x`并將它分配給值 3
```rb
$x = 5
x = 5
```
接下來,我們創建一個函數`print_x`,在其中將`$x`的值更改為 3,因為`$x`是全局的,所以更改在程序中的每個位置都受到影響,接下來我們有了`x = 3`語句,此變量`x`是局部的,與我們在函數外部定義的`x = 5`不同。 接下來,我們將使用以下語句告訴程序打印`$x`和本地`x`的值
```rb
puts "In print_x"
puts "$x = "+$x.to_s
puts "x = "+x.to_s
```
好,當程序遇到`print_x`調用時,我們得到以下輸出
```rb
In print_x
$x = 3
x = 3
```
請注意,`$x`現在為 3,本地`x`也為 3。現在,在函數外部,我們使用以下語句(程序的最后 3 行)打印`$x`和`x`的值
```rb
puts "Outside print_x"
puts "$x = "+$x.to_s
puts "x = "+x.to_s
```
當執行這些語句時,我們得到以下輸出
```rb
Outside print_x
$x = 3
x = 5
```
由于`$x`已分配給 3,因此將 3 作為其值打印。 此處的`x`仍為 5,因為此處`x`并非指`print_x`內部定義的`x`,而是指其中定義的那個。
- 前言
- 紅寶石
- 先決條件
- 1.安裝 Ruby
- 2.在線資源
- 3.入門
- 4.比較與邏輯
- 5.循環
- 6.數組
- 7.哈希和符號
- 8.范圍
- 9.功能
- 10.可變范圍
- 11.類&對象
- 12.安全導航
- 13.打破大型程序
- 14.結構和 OpenStruct
- 15. Rdoc
- 16. Ruby 樣式指南
- 17.模塊和混入
- 18.日期和時間
- 19.文件
- 20. Proc,Lambda 和塊
- 21.多線程
- 22.異常處理
- 23.正則表達式
- 24.寶石
- 25.元編程
- 26.基準
- 27.測試驅動開發
- 28.觀察者模式
- 29.模板模式
- 30.工廠模式
- 31.裝飾圖案
- 32.適配器模式
- 33.單例模式
- 34.復合模式
- 35.建造者模式
- 36.策略模式
- 贊助商
- 捐
- 人們怎么說
- 版權
- 取得這本書