When do Ruby instance variables get set?
1 2 3 4 5 6 7 8 9 | class Hello @hello ="hello" def display puts @hello end end h = Hello.new h.display |
我创建了上面的类。它什么都不打印出来。我以为实例变量@hello是在类声明期间设置的。但当我调用display方法时,输出为"nil"。正确的方法是什么?
Ruby中的实例变量在首次学习Ruby时可能会有点混乱,特别是如果您习惯了像Java这样的另一种OO语言。
不能简单地声明实例变量。
对于Ruby中的实例变量,除了带有@符号前缀的符号外,最重要的一点是它们在第一次被分配时就开始活跃起来。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | class Hello def create_some_state @hello ="hello" end end h = Hello.new p h.instance_variables h.create_some_state p h.instance_variables # Output [] ["@hello"] |
可以使用方法
您通常"声明"并初始化初始化方法中的所有实例变量。明确记录哪些实例变量应该公开的另一种方法是使用模块方法
1 2 3 4 5 6 7 8 9 10 11 12 13 | class Hello attr_accessor :hello end h = Hello.new p h.instance_variables h.hello ="hello" p h.instance_variables # Output [] ["@hello"] |
直到使用合成的
另一个重要的问题,如KCH所描述的,是在声明类时需要注意活动的不同上下文。声明类时,最外层作用域中的默认接收器(self)将是表示类本身的对象。因此,当在类级别上分配给
在方法内部,self将是调用方法的对象,因此您试图打印对象中不存在名为
您需要添加一个
1 2 3 4 5 6 7 8 9 10 11 | class Hello def initialize @hello ="hello" end def display puts @hello end end h = Hello.new h.display |
代码中的第一个
它是类对象的一个实例变量,常量
从技术上讲,当您在
你可以通过观看这个5美元的集合,从务实的程序员那里得到所有这些和更多的澄清。
(或者你可以在这里要求澄清,我会尽量更新。)
在《Ruby编程语言》一书中有一个清晰的描述,阅读它会很有帮助。我把它贴在这里(摘自第7.1.16章):
An instance variable used inside a class definition but outside an
instance method definition is a class instance variable.
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 | class Point # Initialize our class instance variables in the class definition itself @n = 0 # How many points have been created @totalX = 0 # The sum of all X coordinates @totalY = 0 # The sum of all Y coordinates def initialize(x,y) # Initialize method @x,@y = x, y # Sets initial values for instance variables end def self.new(x,y) # Class method to create new Point objects # Use the class instance variables in this class method to collect data @n += 1 # Keep track of how many Points have been created @totalX += x # Add these coordinates to the totals @totalY += y super # Invoke the real definition of new to create a Point # More about super later in the chapter end # A class method to report the data we collected def self.report # Here we use the class instance variables in a class method puts"Number of points created: #@n" puts"Average X coordinate: #{@totalX.to_f/@n}" puts"Average Y coordinate: #{@totalY.to_f/@n}" end end |
……
Because class instance variables are just instance variables of class
objects, we can use attr, attr_reader, and attr_accessor to create
accessor methods for them.
1 2 3 | class << self attr_accessor :n, :totalX, :totalY end |
定义了这些访问器后,我们可以将原始数据称为point.n、point.totalx和point.totaly。
我忘记了Ruby中有一个"类实例变量"概念。无论如何,OP的问题似乎令人费解,之前的任何答案都没有真正解决,除了KCH答案中的一个提示:这是一个范围问题。(在编辑部分增加:事实上,SRIS的答案确实在最后解决了这一点,但我还是让这个答案成立,因为我认为示例代码可能有助于理解问题。)
在Ruby类中,以
一个例子将阐明这一点。下面是一个小Ruby测试类(所有代码都在IRB中测试):
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 | class T @@class_variable ="BBQ" @class_instance_variable_1 ="WTF" @class_instance_variable_2 ="LOL" def self.class_method puts"@@class_variable == #{@@class_variable || 'nil'}" puts"@class_instance_variable_1 == #{@class_instance_variable_1 || 'nil'}" puts"@class_instance_variable_2 == #{@class_instance_variable_2 || 'nil'}" puts"@instance_variable == #{@instance_variable || 'nil'}" end def initialize @instance_variable ="omg" # The following line does not assign a value to the class instance variable, # but actually declares an instance variable withthe same name! @class_instance_variable_1 ="wtf" puts"@@class_variable == #{@@class_variable || 'nil'}" # The following two lines do not refer to the class instance variables, # but to the instance variables with the same names. puts"@class_instance_variable_1 == #{@class_instance_variable_1 || 'nil'}" puts"@class_instance_variable_2 == #{@class_instance_variable_2 || 'nil'}" puts"@instance_variable == #{@instance_variable || 'nil'}" end def instance_method puts"@@class_variable == #{@@class_variable || 'nil'}" # The following two lines do not refer to the class instance variables, # but to the instance variables with the same names. puts"@class_instance_variable_1 == #{@class_instance_variable_1 || 'nil'}" puts"@class_instance_variable_2 == #{@class_instance_variable_2 || 'nil'}" puts"@instance_variable == #{@instance_variable || 'nil'}" end end |
我根据自己的想法来命名变量,尽管事实并非总是这样:
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 | irb> T.class_method @@class_variable == BBQ @class_instance_variable_1 == WTF # the value of the class instance variable @class_instance_variable_2 == LOL # the value of the class instance variable @instance_variable == nil # does not exist in the class scope => nil irb> t = T.new @@class_variable == BBQ @class_instance_variable_1 == wtf # the value of the instance variable @class_instance_variable_2 == nil # the value of the instance variable @instance_variable == omg => #<T:0x000000015059f0 @instance_variable="omg", @class_instance_variable_1="wtf"> irb> t.instance_method @@class_variable == BBQ @class_instance_variable_1 == wtf # the value of the instance variable @class_instance_variable_2 == nil # the value of the instance variable @instance_variable == omg => nil irb> T.class_method @@class_variable == BBQ @class_instance_variable_1 == WTF # the value of the class instance variable @class_instance_variable_2 == LOL # the value of the class instance variable @instance_variable == nil # does not exist in the class scope => nil |
类方法想象地命名为
可以看到,
示例代码中的变量
我还建议查看前缀为"@@"的类变量-下面是一些示例代码,向您展示类和实例变量的不同之处:
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 | class Vars @@classvar="foo" def test @instancevar="bar" end def Vars.show puts"classvar: #{@@classvar}" puts"instancevar: #{@instancevar}" end def instance_show puts"classvar: #{@@classvar}" puts"instancevar: #{@instancevar}" end end # only shows classvar since we don't have an instance created Vars::show # create a class instance vars = Vars.new # instancevar still doesn't show b/c it hasn't been initialized vars.instance_show # initialize instancevar vars.test # now instancevar shows up as we expect vars.instance_show |