4

我正在尝试处理 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...elseflagtest 方法之前)?

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

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

给出以下输出:

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

关于发生什么以及为什么发生的任何线索?

4

3 回答 3

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
于 2013-09-02T15:36:06.813 回答
2

flag = 0 creates a local variable called flag whose scope goes to the end of the method. Any use of flag that appears lexically after that assignment refers to the local variable. Any previous appearance (as well as any appearance of self.flag) refers to the getter method.

So the flag in the else refers to the local variable. Since the local variable never got a value in the else-branch, its value is nil.

于 2013-09-02T15:38:13.447 回答
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"
于 2013-09-02T15:35:42.380 回答