在Ruby中使用匿名模块
假设我制作一个模块,如下所示:在Ruby中使用匿名模块,ruby,module,anonymous,Ruby,Module,Anonymous,假设我制作一个模块,如下所示: m = Module.new do class C end end 三个问题: 除了对m的引用之外,我是否有办法访问C和m中的其他内容 我可以在创建匿名模块后为其命名吗(就像我键入“模块…”) 完成匿名模块后,如何删除它,使其定义的常量不再存在 三个答案: 是,使用ObjectSpace。此代码使c引用您的类c,而不引用m: c = nil ObjectSpace.each_object { |obj| c = obj if (Class
m = Module.new do
class C
end
end
三个问题:
- 除了对
的引用之外,我是否有办法访问m
和C
中的其他内容m
- 我可以在创建匿名模块后为其命名吗(就像我键入“模块…”)
- 完成匿名模块后,如何删除它,使其定义的常量不再存在
- 是,使用
。此代码使ObjectSpace
引用您的类c
,而不引用c
:m
当然,这取决于程序中没有其他名为c = nil ObjectSpace.each_object { |obj| c = obj if (Class === obj and obj.name =~ /::C$/) }
的类,但是您知道了C
- 是的,有点。如果您只是将它赋给一个常量,比如
,那么M=M
将返回M.name
,而不是“M”
,并且像nil
这样的引用将起作用。实际上,当我这样做并在irb中键入M::C
时,我得到了M::C
,但这可能是一个bug::C
- 我认为,一旦没有对它的引用,即当没有
或m
的实例或子类型,并且C
被设置为不同的值或超出范围时,应该对其进行垃圾收集。如果您将其指定给一个常量(如上所述),则还需要将其更改为另一个值(尽管更改常量通常是不明智的)m
M::C
返回name错误:未初始化的常量M::C
和M.constants
返回[]
因此,您应该尝试建议的方法
您可以像往常一样使用m::C
。定义一个NamedModule
处理这个问题的一种方法是定义自己的模块类型,该模块可以用名称初始化
class NamedModule < Module
attr_accessor :name
def initialize(name, &block)
super(&block)
self.name = name
end
def to_s
[self.class.name, name, object_id].join(':')
end
end
将定义为_
可以在祖先中提供良好的输出:
Sailor.ancestors
#=> [Sailor, NamedModule:Piracy:70169997844420, Object, Kernel, BasicObject]
更新-使用命名的gem
在我的同事和我对此进行了实验之后,他编写了一个小型的gem实现。查看命名的gem-and
piracy = NamedModule.new("Piracy") do
def berate
puts "Yer a #{adjectives.sample} #{nouns.sample}!"
end
private
def adjectives
%w[yella-bellied landlubbing]
end
def nouns
%w[scallywag bilge-drinker]
end
end
Sailor = Class.new
Sailor.send(:include, piracy)
Sailor.new.berate #=> "Yer a yella-bellied scallywag!"
Sailor.ancestors
#=> [Sailor, NamedModule:Piracy:70169997844420, Object, Kernel, BasicObject]