## 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.策略模式
- 赞助商
- 捐
- 人们怎么说
- 版权
- 取得这本书