Ruby中Class.new内的baz方法为何无法访问create_B的局部变量foo?
Ruby作用域问题:为什么
baz无法访问foo? 问题出在Ruby的方法作用域规则上:用def定义方法时,会创建一个完全独立的作用域,这个作用域不会继承外部方法(create_B)的局部变量,哪怕你是在外部方法里嵌套定义的类和方法。
具体来说,create_B里的foo是该方法的参数(属于局部变量),而def baz是在动态创建的类内部定义的实例方法——def关键字会隔断它和外部作用域的联系,所以baz里根本找不到foo这个变量。
解决方法有两种:
1. 用define_method代替def(闭包捕获变量)
define_method是方法调用,属于闭包结构,它能捕获外部作用域的局部变量。修改后的代码:
class A def self.create_B(foo) Class.new do define_method(:baz) do p foo end end end end
调用A.create_B(4).new.baz就会输出4,因为define_method定义的baz方法能拿到外部的foo变量。
2. 将foo转为新类的实例变量
把外部的foo值存储到动态类的实例变量里,让baz方法通过实例变量访问:
class A def self.create_B(foo) Class.new do def initialize(foo_arg) @foo = foo_arg end def baz p @foo end end end end
调用时需要传递参数给初始化方法:A.create_B(4).new(4).baz,这样也能正常输出4。如果想简化访问,可以加个attr_reader:
class A def self.create_B(foo) Class.new do attr_reader :foo def initialize(foo_arg) @foo = foo_arg end def baz p foo end end end end
内容的提问来源于stack exchange,提问作者stani gam
相关产品推荐
相关产品推荐

