Is there a way to g开发者_如何学JAVAet all the objects that are of a certain class in Ruby?
To clarify:
class Pokemon
end
pikatchu = Pokemon.new
charmander = Pokemon.new
So, is there a way I could somehow retrieve references those two objects (pikatchu
and charmander
)?
I actually thought of shoving it all into a class array via initialize, but that could potentially grow big, and I am assuming there might be a native Ruby approach to it.
The solution is to use ObjectSpace.each_object
method like
ObjectSpace.each_object(Pokemon) {|x| p x}
which produces
<Pokemon:0x0000010098aa70>
<Pokemon:0x00000100992158>
=> 2
Details are discussed in the PickAxe book Chapter 25
Yes, one could use ObjectSpace
, but in practice one would simply keep track of instances as they are created.
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>]
ObjectSpace
is a simple solution, but note that you can only add to it; removing objects requires garbage collection and that can get messy.
Here's an example of tracking class members that allows you to clear the count. This could be useful, for example, when writing a dummy class for specs.
class Foo
@@instances = []
def initialize
@@instances << self
end
def self.clear
@@instances.clear
end
def self.all
@@instances
end
end
Usage:
(1..10).each { Foo.new }
Foo.all.size # 10
Foo.clear
Foo.all.size # 0
Slightly adjusted, this is probably a good time to use 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">]
精彩评论