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