开发者

Best way to maintain a collection of created objects

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
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜