我想维护一个Klass创建对象的集合。我有两种方法:
第一:通过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
end
end
end
第二:通过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
测试:
a = Klass.new
b = Klass.new
puts a.inspect #=> #<Klass:0xb7786ba0>
puts b.inspect #=> #<Klass:0xb7786b78>
puts Klass.objs.inspect #=> [#<Klass:0xb7786ba0>, #<Klass:0xb7786b78>]
两者都有效,我倾向于选择第二种方式,因为“添加”:它必须是私有的,我必须使用“Klass.send”。什么是最好的方法?还有其他(更好)的方式吗?
答案 0 :(得分:3)
每次创建一个新对象时都会调用正弦初始化,我会利用这个事实并做到:
def initialize *args
# ... do regular initialization ...
@@objs << self
end
答案 1 :(得分:1)
你不能只是在普通构造函数中只是<<
吗?简单的代码,您不必重新定义new
这不是一个好主意。
答案 2 :(得分:1)
请注意,您不需要alias_method
和private
,因为您通常调用的new
为Class#new
。此外,没有理由使用类变量(除非您尝试跟踪主类上的子类创建)。如果不是更好的话,这也很有效:
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>]
此技术优于在初始值设定项中附加到数组的好处是,您无需记住在子类的super
中调用initialize
。实际上,您甚至不需要在子类中定义 initialize
。
答案 3 :(得分:0)
您也可以
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