Fra*_*nce 2 ruby variables module reference
在这样的脚本中,如何从 Klass 引用 x?
module FatherofKlass
module Uncle
x = "my variable's string"
end
module Aunt
end
class Klass
puts x
end
end
Run Code Online (Sandbox Code Playgroud)
我不知道什么样的组合::,@@可以使用,等我。理想情况下,我可以使用一个attr函数,但除了使用常量之外,我尝试过的任何方法都没有奏效。
您无法x从Uncle的定义之外访问——不是您定义它的方式。没关系,因为只需稍作改动,您就可以做到。
要了解您的代码为何不起作用,您需要了解一些关于变量作用域以及 Ruby 如何加载代码的知识。当 Ruby 加载包含模块定义的代码时,它会逐行执行。让我们看看Uncle定义模块时会发生什么。
module Uncle
Run Code Online (Sandbox Code Playgroud)
Ruby 定义模块Uncle并设置self为Uncle. 此外,这是重要的部分,Ruby 创建了一个新的作用域。作用域是存储局部变量的地方。
x = “my variable’s string”
Run Code Online (Sandbox Code Playgroud)
Ruby 定义了局部变量 x并将其设置为"my variable's string". 由于x是局部变量,所以属于当前作用域,即module Uncle声明创建的作用域。
end
Run Code Online (Sandbox Code Playgroud)
这是您的代码出现问题的地方。将end在模块声明的最后销毁包含可变范围x,使其无法到达x。
class Klass
Run Code Online (Sandbox Code Playgroud)
类Klass已创建并self设置为Klass. 然后创建一个新的作用域。
puts x
Run Code Online (Sandbox Code Playgroud)
我们尝试访问x 当前范围内的变量。由于此范围属于 的定义Klass,因此它只能访问在该定义中定义的局部变量。它无法进入Uncle的作用域,即使可以,那也无所谓:Uncle的作用域早已不复存在,它也x随之消失了。
end
Run Code Online (Sandbox Code Playgroud)
如果x不需要更改,则可以将其定义为常量:
module Uncle
X = “my variable’s string”
end
class Klass
puts Uncle::X
end
Run Code Online (Sandbox Code Playgroud)
通过X以全大写命名,Ruby 创建了一个绑定到 module 的常量Uncle。该常量可以在FatherofKlassas Uncle::X(在 之外FatherofKlass,您将使用FatherofKlass::Uncle::X)中的任何地方引用。
顺便说一句,您puts将在定义 Klass时执行。如果你希望它稍后执行,那么把它放在一个方法中:
class Klass
define print_x
puts Uncle::X
end
end
Run Code Online (Sandbox Code Playgroud)
将像这样调用:
k = Klass.new
k.print_x
Run Code Online (Sandbox Code Playgroud)
如果x需要更改,则将其设为常量是行不通的。相反,您可以将其设为类实例变量:
module Uncle
@x = 1
class << self
attr_accessor :x
end
end
class Klass
puts Uncle.x # => 1
Uncle.x = 2
puts Uncle.x # => 2
end
Run Code Online (Sandbox Code Playgroud)
当 Ruby 定义一个用 定义的变量时@,它会将它绑定到self. 因为self是Foo,它创建类实例变量@x。此类实例变量绑定到 module Uncle,因此在 Uncle 定义完成后仍然存在。
不要担心我们已经定义了一个绑定到模块的类实例变量。类和模块在 Ruby 中密切相关。
定义访问器以x创建允许x读取和写入的方法。因为访问器通常访问实例变量,我们需要将它嵌套class << self在其中以便在类实例变量上定义访问器。
| 归档时间: |
|
| 查看次数: |
634 次 |
| 最近记录: |