0

I'm trying to keep track of all instantiated subclass objects in an array in the super, so that I can call a method from super to iterate over them. I think I'm almost there but I can't figure out what I'm missing. Currently when I call super.my_array it's only returning an empty array, so there has to be something wrong with my initialize method. This is the abstracted version have I have so far:

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 Answers 4

2

I'm going to provide an alternative answer to your question...

Honestly, I'd probably switch your approach on this a bit and create a separate class (that includes the Singleton module) with which your Klass registers, e.g.

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

Additionally, this by its very nature is going to leak memory like crazy, so I would recommend storing weak/soft references either using WeakRef or a library like ref (which I haven't used or seen before, but looks like what you'd want) and only tracking weak/soft references in your KlassTracker class.

Lastly, I'd be remiss if I didn't mention that what you're asking to do is, frankly, somewhat crazy. I don't know what you're trying to do, but there's probably a better approach.

Sign up to request clarification or add additional context in comments.

3 Comments

Additionally, if you'd rather not have the runtime overhead and complexity of maintaining this list of instances, ObjectSpace.each_object(Klass) is another alternative.
It's for a programming challenge that I'm stuck on, so performance isn't really a concern. I'm just trying to improve my ruby skills, but thanks for pointing me in the right direction!
Ah, interesting...in general, I try to stay away from @@-variables (class variables). Compared to their Java counterparts, they're frighteningly hard to use predictably. Hence my tendency towards the Singleton mixin.
1

Not sure what You are trying to achieve, but I see a few potential problems.

attr_reader defines an accessor on instance level, so it has nothing to do with class variable. Basically when You say attr_reader :my_array, it defines a method like this

def my_array
  @my_array
end

Secondly You will be better of checking type like this:

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

Here is an example that does what You need if I understood You correctly.

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>]

Comments

0

To iterate over instances of a specific class, you can use 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 }

Output:

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

Or as a class method:

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

Foo.each_instance { |x| p x }

Comments

0

Would this meet your needs?

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'

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.