I want to maintain a collection of created objects of a Klass. I have two methods im mind:
First: Thru initialize
:
class Klass
@@objs = []
def initialize *args
# ... do regular initialization ...
Klass.send :add, self
end
class << self
def objs
@@objs
end
private
def add obj
@@objs << obj
开发者_如何学Pythonend
end
end
Second: Thru new
:
class Klass
@@objs = []
class << self
def objs
@@objs
end
alias_method :old_new, :new # never thought someday I'd name something as "old_new"!
private :old_new
def new *args
obj = super
@@objs << obj
obj
end
end
end
Testing:
a = Klass.new
b = Klass.new
puts a.inspect #=> #<Klass:0xb7786ba0>
puts b.inspect #=> #<Klass:0xb7786b78>
puts Klass.objs.inspect #=> [#<Klass:0xb7786ba0>, #<Klass:0xb7786b78>]
Both works, and I tend to prefer the second way, because of "add": it must be private, and I must use "Klass.send". What is the best way? Is there some other (better) manner?
Sine initialize is called every time a new object is created, I would take advantage of this fact and just do:
def initialize *args
# ... do regular initialization ...
@@objs << self
end
Couldn't you simply just <<
in the normal constructor? Simple code and you don't have to redefine new
which is rarely a good idea.
Note that your alias_method
and private
were not needed, as the new
you normally call is Class#new
. Also, there's no reason to use a class variable (unless you are trying to track sub-class creations on the master class). This works just as well, if not better:
class Foo
class << self; attr_reader :objs; end
def self.new(*a,&b)
super.tap{|o| (@objs||=[]) << o}
end
end
class Bar < Foo; end
2.times{ Foo.new }
3.times{ Bar.new }
p Foo.objs
#=> [#<Foo:0x2bb6260>, #<Foo:0x2ba2400>]
p Bar.objs
#=> [#<Bar:0x2ce6000>, #<Bar:0x2baf4e0>, #<Bar:0x2b94f40>]
The benefit of this technique over appending to the array in your initializer is that you don't need to remember to call super
in the initialize
of your subclasses. Indeed, you don't need to even define an initialize
in your subclasses.
You could also do
class IndividualKlass
end
class KlassCreator
def initialize(individual_klass)
@individual_klass = individual_klass
@objects = []
end
def create_object
object = @individual_klass.new
@objects << object
object
end
end
klass_creator = KlassCreator.new(IndividualKlass)
IndividualKlass = nil # Or remove_const or something
object = klass_creator.create_object
精彩评论