Module that keeps track of instance count?

Hi,

I need some of my classes to keep track of their number of instances.
To avoid duplication I thought it was a good idea to put this
functionality in a separate module:

module InstanceCounter
   def initialize(*args)
      super
      @count = 0
   end

   def increase_count()
      @count += 1
      return @count - 1
   end

end

class Widget

   def initalize(name)
      @name = name
   end

end

class Caption < Widget

   include InstanceCounter

   def initialize()
      super("Widget_Nr" + increase_count().to_s)
   end

end

The problem seems to be that I need the functionality of
InstanceCounter when is has not you been initialized. Does anybody see
some light here? Perhaps a different approach will do?

Best regards,
Francis

I think you want, instead:

  module InstanceCounter
    def increase_count
      @@count ||= 0
      @@count += 1
      (@@count - 1)
    end
  end

Note that this isn't thread-safe. It also won't help in cases where
you subclass your class that includes InstanceCounter. What you'd
probably want is something that deals with a class-instance variable
rather than a class variable, and that would be able to be dealt
with using #append_features (I think). Additionally, under the
current scheme, #increase_count is a public method that anyone can
call on an instance.

There are examples of how to get create this count safely somewhere,
I just can't recall where offhand. :wink:

The main trick you're after, though, is @@count ||= 0.

-austin

···

On 8/2/05, francisrammeloo@hotmail.com <francisrammeloo@hotmail.com> wrote:

I need some of my classes to keep track of their number of
instances. To avoid duplication I thought it was a good idea to
put this functionality in a separate module:

module InstanceCounter
  def initialize(*args)
    super
    @count = 0
  end

  def increase_count()
    @count += 1
    return @count - 1
  end
end

--
Austin Ziegler * halostatue@gmail.com
               * Alternate: austin@halostatue.ca

<francisrammeloo@hotmail.com> wrote...

Hi,

I need some of my classes to keep track of their number of instances.
To avoid duplication I thought it was a good idea to put this
functionality in a separate module:
<snip counting code>

Here's a different way to do it:

module InstanceCounter
  def instance_count(include_subclasses = true)
    count = 0
    GC.start # <- this line is optional
    ObjectSpace.each_object do |obj|
      count += 1 if obj.class == self || include_subclasses &&
obj.kind_of?(self)
    end
    count
  end
end

class Foo
  extend InstanceCounter
end

class Bar < Foo
end

Foo.instance_count #=> 0
Bar.instance_count #=> 0
a = [Foo.new, Bar.new, Bar.new]
Foo.instance_count #=> 3
Foo.instance_count(false) #=> 1
Bar.instance_count #=> 2

Cheers,
Dave

This works for me:

module InstanceCounter

   def increase_count( type_name )
      @@instance_counter ||= Hash.new
      @@instance_counter[type_name] ||= 0
      @@instance_counter[type_name] += 1
      return @@instance_counter[type_name] - 1
   end
  
end

I don't know how this conforms to Ruby programming style, but you can
extend the singleton design pattern and have a class method that
controls the initialization of Caption.

class Widget
  attr_reader :name

  def initialize(name)
    @name = name
  end
end

class Caption < Widget
  def Caption.get_new_instance
    @@count ||= 0
    @@count += 1
    return Caption.new
  end

  private

  def initialize
    super("Widget_Nr" + (@@count-1).to_s)
  end
end

a = Array.new
(1..10).to_a.each do |i|
  a << Caption.get_new_instance
end

a.each do |e|
  puts e.name
end

output:
Widget_Nr0
Widget_Nr1
Widget_Nr2
Widget_Nr3
Widget_Nr4
Widget_Nr5
Widget_Nr6
Widget_Nr7
Widget_Nr8
Widget_Nr9

The private initialize method makes sure that no one ever calls
Caption.new explicitly and you can only get new instances of Caption by
calling the get_new_instance class method.