我已经使用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
我们在这里有什么:
- 具有@in_progress变量的吸气器和二传手的类游戏
- 默认情况下@in_progress为假
- 我们调用 start! 方法并尝试将in_progress更改为 true
- 吸气剂in_progress效果很好
- Setter 只与 self 一起工作,或者通过 @in_progress 直接访问变量
我读到了 Ruby 中的方法查找(向右走一步进入接收器的类,然后沿着祖先链向上,直到找到方法。但我真的不知道为什么我必须使用 self.in_progress=true 才能访问 setter 方法。特别是当吸气方法在没有自我的情况下工作时。
提前感谢!
因为您正在为函数中的局部变量in_progress
赋值,而不是实例变量。getter 之所以有效,是因为 Ruby 会查询 start!
函数的本地命名空间以获取in_progress
,它找不到它,然后它会查询实例命名空间,它会找到一个名为 in_progress
的方法并调用它。
Ruby 解释器无法确定您是要在局部in_progress
还是在实例变量上分配 true
值,因此规则是在本地分配它(到 start!
中的当前命名空间)。
当你做in_progress = true
时,你实际上在你的方法中创建了一个局部变量,而不是访问你的setter。
当你做puts in_progress
时,Ruby 会检查一个in_progress
局部变量,当它找不到它时,它会去找你类的 getter。
尝试做in_progress = 'hello'
,然后做puts in_progress
。你会意识到Ruby将使用局部变量in_progress
。