Ruby:为何在case语句中给实例变量赋值需加self?
为什么Ruby中调用attr_accessor生成的setter方法必须加self?
这本质是Ruby的变量解析规则和方法调用机制的问题,核心区别在于局部变量赋值和方法调用的优先级:
赋值语句会优先创建局部变量
当你写working_dir = ['/']时,Ruby解释器会默认把这当成一个局部变量定义/赋值,而不是调用attr_accessor生成的working_dir=setter方法。哪怕你已经通过attr_accessor定义了同名的setter,解释器也会优先处理成局部变量,这就导致原本要给实例变量@working_dir赋值的逻辑失效,甚至触发Rubocop警告(比如“assigned but unused variable”)。非赋值操作会自动查找实例方法
当你执行working_dir.pop或者working_dir << 'subdir'时,这里没有赋值行为,Ruby会先检查当前作用域有没有同名局部变量——如果没有,就会自动调用attr_accessor生成的getter方法working_dir,拿到实例变量@working_dir的引用,然后对这个对象执行修改操作(pop/<<都是修改对象本身,不是重新赋值)。这时候不需要加self.,因为解释器能明确识别这是方法调用。
用你的代码举个更清晰的例子:
class FileSystem attr_accessor :working_dir def initialize @working_dir = ['/'] end def parse_cmd(cmd) case cmd when 'cd ..' # 等价于 self.working_dir.pop,自动调用getter方法 working_dir.pop when 'cd /' # 必须加self,否则会定义局部变量working_dir self.working_dir = ['/'] when 'cd sub' # 自动调用getter,修改@working_dir指向的数组对象 working_dir << 'sub' end end end
简单总结:
- 要调用setter方法(给实例变量重新赋值),必须用
self.前缀,明确告诉Ruby这是方法调用,不是局部变量赋值 - 调用getter方法或修改getter返回的对象时,因为没有赋值行为,Ruby会自动匹配实例方法,无需加
self.
内容的提问来源于stack exchange,提问作者Steed-Asprey
相关产品推荐
相关产品推荐

