Richard
Richard

Reputation: 6116

Ruby Defining Class Variables

I went to this page to learn about Ruby classes. The code on that page is this:

class Customer
   @@no_of_customers=0
   def initialize(id, name, addr)
      @cust_id=id
      @cust_name=name
      @cust_addr=addr
   end
   def display_details()
      puts "Customer id #@cust_id"
      puts "Customer name #@cust_name"
      puts "Customer address #@cust_addr"
   end
   def total_no_of_customers()
      @@no_of_customers += 1
      puts "Total number of customers: #@@no_of_customers"
   end
end

I understand @@ means class variable, but I don't understand how you can create a variable in the initialize method (constructor) and use it inside another method as if it's a class variable. How is this possible? What is the point of defining class variables if you can just define it in the constructor?

Upvotes: 0

Views: 2244

Answers (2)

mjgpy3
mjgpy3

Reputation: 8937

If I'm understanding your question correctly (please comment if I am not), you are asking why we don't usually define class variables in constructors.

In your above code example, the @@no_of_customers class variable is not defined in the constructor because it is meant to be accessible to all members of that class and it keeps track of the number of customers. So, if our constructor looked like this:

def initialize(id, name, addr)
  @@no_of_customers=0
  @cust_id=id
  @cust_name=name
  @cust_addr=addr
end

we would be overwriting that variable with 0 every time someone defines a new instance of that class. A more appropriate class definition would look like this:

class Customer
  @@no_of_customers=0
  def initialize(id, name, addr)
    @@no_of_customers += 1
    @cust_id=id
    @cust_name=name
    @cust_addr=addr
  end
  ...
end

So, the class variable @@no_of_customers is initialized at zero before we instantiate any objects. Then each time we create a new object we increment it.

Of course, the reasons one might use a class variable for this example are:

  • It makes sense to encapsulate the number of customers with the customers and not use some global

  • Because it is attached to the customer class, the outside world can't modify it and make it mean something other than what it's supposed to mean, or do something unexpected with it.

This is all to say, it's sort of like the "don't play with strangers" rule.

@ vs. @@

When @ is used as a prefix in ruby, it designates that the variable is an instance variable.

When @@ is used, this means that it is a class variable.

Here's a nice article on the difference between these if you aren't aware.

Upvotes: 4

Julien Langlois
Julien Langlois

Reputation: 480

I think you are confusing class (@@) and instance (@) variables. In Ruby a class variable is more like a static class variable in C++, and instance variables are like regual class variables in C++:

class Test
    @@cvar = 1
    def initialize
        @ivar = 0
    end
end

is more or less equivalent to (sorry, my C++ is rusty):

class Test {
    public:
        Test() : ivar(0) {}
    private:
        static int cvar;
        int ivar;
};
int Test::cvar = 1;

Upvotes: 3

Related Questions