akallel
akallel

Reputation: 13

Ruby class object extension

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

Answers (2)

Cary Swoveland
Cary Swoveland

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

user513951
user513951

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

Related Questions