混淆的实例变量作用域,顶层 vs 类

4

我一直在顶层使用Ruby进行尝试,通常编写的代码如下:

@x = 'foo'
def show_var
  puts @x
end

show_var # => foo

根据这个例子的工作方式,我认为实例变量对类和对象都是可用的。

今天我遇到了这个问题,看起来我的实例变量理解是不正确的:

class Test
  @x = "foo" #you would need to define this inside 'initialize' for this to be available to show_var
  def show_var
    puts @x
  end 
end

Test.new.show_var # => nil

看起来第二个例子展示了实例变量的工作原理。如果在类内定义实例变量,则其仅存在于该范围内,并且不存在于实例方法中。

那么我的问题是...为什么第一个例子输出 'foo',当变量 @x 不应该存在于实例方法的范围内? 另外,在顶层类中定义变量的正确方法是什么,以便您可以在顶级方法中使用它们?


1
除了已经给出的答案之外,可以尝试使用Test.instance_variable_get(:@x) - 实例变量@x已经在Test类上定义(它是一个类型为Class的对象)- 可能需要一些时间才能意识到这意味着什么,但这是理解Ruby的关键部分。 - Neil Slater
在您的最后一个示例中,您创建了所谓的“类实例变量”。它们比类变量(@@)更受欢迎。 - 7stud
2个回答

5

第一个例子中的方法位于顶层。这意味着它属于一个特殊的顶层对象main。你不能真正创建更多的main副本,因此该方法内外的self是相同的。看一下这个:

self # => main
def show_var
  self # => main
end

class Test
  self # => Test
  def show_var
    self # => #<Test:0x007fdf9c892d70>
  end 
end

1
请看下方:
@x = 'foo'
def show_var
  puts @x,self
  p defined? @x
end

show_var
# >> foo
# >> main
# >> "instance-variable"

在第一种情况下,您在“main”范围内定义了“@x”。然后,当从“main”调用方法“show_var”时,您会得到“@x”的输出,这不是其他情况的情况。
class Test
  @x = "foo" 
  def show_var
    p @x,self 
    p defined? @x
  end 
end

Test.new.show_var
# >> nil
# >> #<Test:0x9b6fcd4>
# >> nil

哦,好的,谢谢。如果我要执行以下代码:class Test; @x='foo';def self.show_var; puts @x; end; show_var; end; Test.new 那么我在顶层所做的就是输出'foo'。 - MichaelHajuddah

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接