Ruby中如何无需eval访问Module.new定义的内部类?
问题解析与解决方案
当你用Module.new的代码块定义内部类时,块的执行作用域是当前顶层作用域,而非模块自身的作用域。这意味着你在块里写的class MyClass实际上创建的是顶层的::MyClass,而非Mod::MyClass,所以外部直接调用Mod::MyClass会报常量未定义的错误。而用module关键字定义模块时,代码块的作用域是模块内部,类会被正确注册到模块的常量列表中。
不用eval的话,有两种直接的解决方法:
方法一:明确指定类的所属模块
在定义类时,直接通过self::MyClass来指定类的归属,确保类被注册到模块的常量中:
Mod = Module.new do class self::MyClass attr_reader :a def initialize(a) @a = a end end end # 现在可以直接访问 puts Mod::MyClass.new(1).a # 输出 1
方法二:直接赋值模块内部常量
通过Class.new创建类对象,然后将其赋值给模块内部的MyClass常量:
Mod = Module.new do MyClass = Class.new do attr_reader :a def initialize(a) @a = a end end end # 同样可以直接访问 puts Mod::MyClass.new(1).a # 输出 1
你之前尝试Mod.instance_eval { public_constant :MyClass }失败,是因为MyClass根本没有被注册为Mod的常量,自然找不到这个常量来设置公开属性。
内容的提问来源于stack exchange,提问作者Artem Yegorov
相关产品推荐
相关产品推荐

