5

我已经使用 Ruby 有一段时间了。现在我要深入挖掘并找到所有问题的答案。我希望我能在这里找到答案。所以这是我在下面代码中的问题:

class Game

  attr_accessor :in_progress

  def initialize
    @in_progress = false
  end

  def start!

    # debug info                                                                         
    puts self.inspect                        # => #<Game:0x8f616f4 @in_progress=false>
    puts self.class.instance_methods(false)  # => [:in_progress, :in_progress=, :start!]
    puts self.instance_variables             # => [:@in_progress]
    puts self.respond_to?("in_progress=")    # => true

    puts in_progress      # => true - getter works without self
    # main quesion
    in_progress = true    # Why setter doesn't work without self?

    # self.in_progress = true   # this would work and set @in_progress to true becase setter called
    # @in_progress = true       # this would work as well because we set instance variable to true directly

  end

end

g = Game.new
g.start!
puts g.in_progress # => false - setter in start! method didn't work

我们在这里有什么:

  1. 类 Game 与 @in_progress 变量的 getter 和 setter
  2. @in_progress 默认为 false
  3. 我们叫开始!方法并尝试将 in_progress 更改为 true
  4. in_progress 的吸气剂效果很好
  5. Setter 仅适用于 self。或通过@in_progress 直接访问变量

我读到了 Ruby 中的方法查找(向右走一步进入接收者的类,然后沿着祖先链向上,直到找到方法。)但我真的不知道为什么我必须使用 self.in_progress=true访问setter方法。特别是当 getter 方法在没有 self 的情况下工作时。

提前致谢!

4

2 回答 2

8

因为您正在为函数中的局部变量分配值in_progress,而不是实例变量。getter 起作用是因为 Ruby 会查询start!函数的本地命名空间 for in_progress,它不会找到它,然后它会查询实例命名空间,它会找到一个被调用的方法in_progress并调用它。

Ruby 解释器无法确定您是要true在本地in_progress还是在实例变量上分配值,因此规则是在本地分配它(分配给 中的当前命名空间start!)。

于 2013-10-27T10:52:27.813 回答
2

当你这样做时in_progress = true,你实际上在你的方法中创建了一个局部变量,而不是访问你的 setter。

当你这样做时puts in_progress,Ruby 会检查一个in_progress局部变量,当它找不到它时,它会寻找你类的 getter。

尝试做in_progress = 'hello'然后做puts in_progress。您将意识到 Ruby 将使用局部变量in_progress

于 2013-10-27T10:55:57.757 回答