如何在Ruby中查找类的每个实例

时间:2011-05-26 21:07:21

标签: ruby reflection

有没有办法在Ruby中获取某个类的所有对象?

澄清:

class Pokemon
end

pikatchu = Pokemon.new
charmander = Pokemon.new

那么,有没有办法可以以某种方式检索这两个对象的引用(pikatchucharmander)?

我实际上想过通过初始化把它全部推到一个类数组中,但这可能会变大,我假设可能有一个原生的Ruby方法。

4 个答案:

答案 0 :(得分:28)

解决方案是使用{/ 1}}方法,如

ObjectSpace.each_object

产生

ObjectSpace.each_object(Pokemon) {|x| p x}

详情在PickAxe book第25章

中讨论

答案 1 :(得分:2)

ObjectSpace是一个简单的解决方案,但请注意,您只能对其进行添加;删除对象需要进行垃圾收集,并且可能会变得凌乱。

这是一个跟踪类成员的示例,可让您清除计数。例如,在为规范编写虚拟类时,这可能很有用。

class Foo
  @@instances = []

  def initialize
    @@instances << self
  end

  def self.clear
    @@instances.clear
  end

  def self.all
    @@instances
  end
end

用法:

(1..10).each { Foo.new }
Foo.all.size # 10
Foo.clear
Foo.all.size # 0

答案 2 :(得分:0)

是的,人们可以使用ObjectSpace,但实际上,人们只会在创建实例时跟踪它们。

class Pokemon
  @pokees = []
  self.class.public_send(:attr_reader, :pokees)

  def initialize
    self.class.pokees << self
  end
end

pikatchu = Pokemon.new
  #=> #<Pokemon:0x00005c46da66d640> 
charmander = Pokemon.new
  #=> #<Pokemon:0x00005c46da4cc7f0> 
Pokemon.pokees
  #=> [#<Pokemon:0x00005c46da66d640>, #<Pokemon:0x00005c46da4cc7f0>] 

答案 3 :(得分:0)

稍作调整,这可能是使用Enumerator#to_a的好时机:

Pokemon.new("Charmander")
#=> #<Pokemon:0x00007fe4226658d8 @name="Charmander">
Pokemon.new("Sandshrew")
#=> #<Pokemon:0x00007fe424822cf0 @name="Sandshrew">

ObjectSpace.each_object(Pokemon).to_a
#=> [#<Pokemon:0x00007fe4226658d8 @name="Charmander">, #<Pokemon:0x00007fe424822cf0 @name="Sandshrew">]