假设我制作一个模块如下:
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
,并且引用 likeM::C
将起作用。实际上,当我这样做并输入M::C
irb 时,我得到#<Module:0x9ed509c>::C
了 ,但也许这是一个错误。
m
垃圾C
收集m
。如果您将其分配给上述点的常量,您也需要将其更改为不同的值(尽管更改常量通常是不明智的)。处理此问题的方法之一是定义您自己的可以用名称初始化的模块。
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
然后你可以这样做:
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!"
定义to_s
给你很好的输出ancestors
:
Sailor.ancestors
#=> [Sailor, NamedModule:Piracy:70169997844420, Object, Kernel, BasicObject]
我在 Ruby 1.9.3-p0 中尝试了 wdebeaum 的第二个回答,但没有成功。
M::C
返回NameError: uninitialized constant M::C
并M.constants
返回[]
所以你应该尝试这里建议的方法
m = Module.new do
class self::C
end
end
您可以m::C
照常使用。