将实例化的子类添加到超类中的数组

时间:2013-10-12 17:28:00

标签: ruby oop inheritance

我正在尝试跟踪super中数组中所有实例化的子类对象,以便我可以从super调用一个方法来迭代它们。我想我差不多了,但我无法弄清楚我错过了什么。目前,当我调用super.my_array时,它只返回一个空数组,因此我的initialize方法必定存在问题。这是我到目前为止的抽象版本:

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 个答案:

答案 0 :(得分: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

此外,这本质上就像疯了一样泄漏内存,所以我建议使用WeakRef或像ref这样的库存储弱/软引用(我没有用过)或者之前看过,但看起来像你想要的那样)并且只跟踪KlassTracker类中的弱/软引用。

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

答案 1 :(得分: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>]

答案 2 :(得分: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 }

答案 3 :(得分: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'