了解Ruby中的范围

时间:2013-09-02 15:26:13

标签: ruby recursion scope

我正在尝试处理Ruby中非常奇怪(至少对我而言)的情况。我的代码如下:

class ScopeTest
  attr_accessor :flag

  def flagtest
    puts "SELF: " + self.flag.to_s
    puts "INST: " + flag.to_s
    if flag == 1
      flag = 0
      puts "SELF: " + self.flag.to_s
      puts "INST: " + flag.to_s
      self.flag = 0
      puts "SELF: " + self.flag.to_s
      puts "INST: " + flag.to_s
      flagtest
    else
      puts "SELF: " + self.flag.to_s
      puts "INST: " + flag.to_s
    end
  end
end

st = ScopeTest.new
st.flag = 1
st.flagtest

输出如下:

SELF: 1
INST: 1
SELF: 1
INST: 0
SELF: 0
INST: 0
SELF: 0
INST: 0
SELF: 0
INST: 

奇怪的是flag变量nil是我最后一次打印它(else内)但0之前(if...else之前class ScopeTest attr_accessor :flag def flagtest puts "SELF: " + self.flag.to_s puts "INST: " + flag.to_s if flag == 1 self.flag = 0 puts "SELF: " + self.flag.to_s puts "INST: " + flag.to_s flagtest else puts "SELF: " + self.flag.to_s puts "INST: " + flag.to_s end end end st = ScopeTest.new st.flag = 1 st.flagtest 在flagtest方法中)?

当我删除几行代码时,一切似乎恢复正常,如下面的代码:

SELF: 1
INST: 1
SELF: 0
INST: 0
SELF: 0
INST: 0
SELF: 0
INST: 0

给出以下输出:

{{1}}

有关发生的事情和原因的任何线索?

3 个答案:

答案 0 :(得分:3)

这是因为你已经分配了一个局部变量flag = 0。 IIRC,局部变量在解析时创建,并作用于方法。默认情况下,它们会使用nil进行初始化。因此,在then子句中,在访问它之前为其分配值。但是当您重新输入该方法时,您会转到else子句,flag保持未初始化状态(即nil)。

class ScopeTest
  attr_accessor :flag

  def flagtest
    # if you comment this line, the method will output 1, 1
    # if you don't comment, it will output 1, nil, because the assignment to local variable was never done.
    #   but local var itself was created.
    flag = 3 if false

    puts self.flag.inspect
    puts flag.inspect
  end
end

st = ScopeTest.new
st.flag = 1
st.flagtest
# >> 1
# >> nil

答案 1 :(得分:2)

查看原因: -

class ScopeTest
  attr_accessor :flag

  def flagtest
    p defined?(flag)
    if flag == 1
      p defined?(flag)
      flag = 0
      p defined?(flag)
      self.flag = 0
      flagtest
    else
      p defined?(flag)
    end
  end
end

st = ScopeTest.new
st.flag = 1

输出

"method"
"method"
"local-variable"
"method"
"local-variable"

答案 2 :(得分:2)

flag = 0创建一个名为flag的局部变量,其范围到达方法的末尾。在该赋值之后以词法形式出现的flag的任何使用都是指局部变量。任何先前的外观(以及self.flag的任何外观)都指的是getter方法。

因此flag中的else指的是局部变量。由于局部变量从未在else - 分支中获得值,因此其值为nil