Ruby 2.3.4中attr_accessor可取值却无法赋值的问题排查
问题根源与解决方案
嘿,我来帮你理清这个问题!你遇到的报错是因为Ruby的变量作用域规则在搞鬼——当你在方法里直接写update_me = ...或者update_me += 1时,Ruby会默认把update_me当成一个局部变量,而不是调用attr_accessor生成的setter方法。
咱们一步步拆解代码的运行过程:
puts update_me这行没问题,因为这里是读取变量,Ruby会优先调用getter方法,拿到实例变量@update_me的初始值6,所以输出6。- 到
update_me += 1时,Ruby会先检查有没有名为update_me的局部变量——这时候还没有,所以它会把这个变量初始化为nil,然后尝试对nil调用+方法,自然就抛出undefined method '+' for nil:NilClass的错误了。
两种实用解决办法
办法一:显式用self调用setter方法
在Ruby中,调用实例方法时加上self.前缀,就能明确告诉Ruby要调用对象的setter方法,而不是创建局部变量。修改后的代码如下:
class Blah attr_accessor :update_me def initialize @update_me = 6 end def addy puts update_me if update_me.nil? self.update_me = 1 else self.update_me += 1 end end end
这种方式更推荐,因为如果以后你需要给update_me的setter加额外逻辑(比如值的校验、格式转换),直接修改setter方法即可,不需要改动调用它的代码。
办法二:直接操作实例变量@update_me
既然attr_accessor是围绕实例变量@update_me生成的getter和setter,你也可以直接访问这个实例变量来更新值:
class Blah attr_accessor :update_me def initialize @update_me = 6 end def addy puts @update_me if @update_me.nil? @update_me = 1 else @update_me += 1 end end end
这种方式更直接,但缺点是如果以后修改了实例变量的名字或者给setter加了逻辑,你就得手动修改所有直接访问的地方。
现在你再去irb里测试修改后的代码,就可以正常更新update_me的值啦!
内容的提问来源于stack exchange,提问作者tracyjs
相关产品推荐
相关产品推荐

