Reputation: 13
I'm new to Ruby and I have been trying to learn metaprogramming. I want to define a class and count the number of objects created then print it out when ClassName.Count
is called. (This will give the number of objects that have been created).
This is what I have so far:
class Test
@@number = 0
def initialize
@@number += 1
end
def self.Count
puts "number is #{@@number}"
end
end
Test.Count() # => 0
test1 = Test.new
test2 = Test.new
Test.Count() # => 2
test3 = Test.new
Test.Count() # => 3
This works and prints the right number of objects created. However, I am supposed to do this using class object extension, that is without using self methods (self.foo
) or class attributes (@@number
). This is where I got stuck. I'm not sure what the difference is between my solution and the one I need to implement. Also any suggestions for readings about this topic would be more than welcome.
Upvotes: 1
Views: 257
Reputation: 110665
Does this meet your requirements?
class Test
@count = 0
def initialize
Test.instance_variable_set(:@count, Test.instance_variable_get(:@count)+1)
end
def count
Test.instance_variable_get(:@count)
end
end
Test.instance_variable_get(:@count)
#=> 0
test1 = Test.new
test1.count
#=> 1
test2 = Test.new
test2.count
#=> 2
test1.count
#=> 2
Test.instance_variable_get(:@count)
#=> 2
Upvotes: 1
Reputation: 13612
It's true that you really should never use "class variables" (e.g. @@foo
); they aren't what most people think they are, and they behave in surprising / stupid ways. In most cases when you think you need a "class variable", really all you need is an instance variable on the class itself (which, as an object, is an instance itself, of the class Class
).
I don't know why you aren't allowed to define singleton methods (i.e. "self methods"), but here is another way of doing it using the class << self
syntax.
class Test
@count = 0
class << self
attr_accessor :count
end
def initialize
self.class.count += 1
end
end
Upvotes: 1