0

我试图跟踪超级数组中所有实例化的子类对象,以便我可以从超级调用一个方法来迭代它们。我想我快到了,但我不知道我错过了什么。目前,当我调用 super.my_array 时,它只返回一个空数组,所以我的初始化方法一定有问题。这是我到目前为止的抽象版本:

class Klass
  attr_reader :my_array
  @@my_array = []
  def initialize
    @@my_array << self if super.class == Klass
  end
  def self.iterate_over_sub
    @@my_array.each { |x| x.sub_method }
  end
  def sub_method
    puts "#{self.class} is being called by super"
  end
end
4

4 回答 4

2

我将为您的问题提供替代答案...

老实说,我可能会稍微改变一下你的方法,并创建一个单独的类(包括 Singleton 模块),你的 Klass 会在其中注册,例如

class Klass
    def initialize
        KlassTracker.instance.track(self)
    end
end

require 'singleton'
class KlassTracker
    include Singleton
    def initialize
        @instances = []
    end
    def track(instance)
        @instances << []
    end
 end

此外,从本质上讲,这会像疯了一样泄漏内存,所以我建议使用Wea​​kRef或像ref这样的库来存储弱/软引用(我以前没有使用过或见过,但看起来像你想要的那样想要)并且仅在您的 KlassTracker 类中跟踪弱/软引用。

最后,如果我没有提到你要求做的事情,坦率地说,有点疯狂,那我就失职了。我不知道你想做什么,但可能有更好的方法。

于 2013-10-12T17:41:37.403 回答
1

不确定您要达到的目标,但我看到了一些潜在的问题。

attr_reader 在实例级别定义了一个访问器,因此它与类变量无关。基本上当你说时attr_reader :my_array,它定义了一个这样的方法

def my_array
  @my_array
end

其次你会更好地检查这样的类型:

@@my_array << self if self.is_a?(Klass)

如果我正确理解了你,这里有一个例子可以满足你的需要。

class Klass
  @@my_array = []

  def self.my_array
    @@my_array
  end

  def initialize
    @@my_array << self if self.is_a?(Klass)
  end
  def self.iterate_over_sub
    @@my_array.each { |x| x.sub_method }
  end
  def sub_method
    puts "#{self.class} is being called by super"
  end
end

class SubKlass < Klass
end

sk = SubKlass.new
#<SubKlass:0x007f8ecb861eb8>
Klass.my_array
#[#<SubKlass:0x007f8ecb861eb8>]
于 2013-10-12T17:45:59.207 回答
0

要迭代特定类的实例,您可以使用ObjectSpace::each_object

class Foo; end
class Bar < Foo; end
class Baz < Foo; end

Foo.new
Bar.new
Baz.new

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

输出:

#<Baz:0x007fc213859710>
#<Bar:0x007fc213859738>
#<Foo:0x007fc213859760>

或作为类方法:

class Foo
  def self.each_instance(&block)
    ObjectSpace.each_object(self, &block)
  end
end

Foo.each_instance { |x| p x }
于 2013-10-12T17:51:56.573 回答
0

这能满足您的需求吗?

class A
  @@instances = []
  def self.new
    a = super
    @@instances << a
    a
  end   
  def self.tryit
    @@instances.each {|e| e.test}
  end  
end

class B < A
  def test
    puts "hi"
  end        
end
b = B.new
c = B.new
b.test # => 'hi'
A.tryit # => 'hi\nhi'
于 2013-10-13T03:49:44.007 回答