2.1 Class Variables and Methods

Things that we already know

You already know what an instance method is:
Example Code:

Output Window

Both initialize and show are instance methods. Just like instance variables, they work with instances of a Class.

Let us compare them with a class method:

Example Code:

Output Window

In def self.show, the keyword self denotes that the method show is being defined in the context of the Class itself, not its instances. Any method definition without the self qualifier is by default an instance method.

There is also another way to define class methods that you may come across in Ruby code:

Example Code:

Output Window

Class methods do not have access to instance methods or instance variables. However instance methods can access both class methods and class variables.

In the next section, we'll see how we can use class methods with class variables to achieve something useful.

Using class variables to store application configuration

In the following example, we define a class Planet that keeps count of the number of instances of Planets ever created.

Recall that an instance variable always has an @ symbol prefixed before its name. Similarly, class variables are prefixed with @@.

Example Code:

Output Window

As you can see, class variables can be used to store data that belongs to a class, but not to its instances.

There aren't very many cases that you would need to use class variables. In fact, its improper usage is generally frowned in the Ruby community.

One of the places where class variables do find proper use is to store application configuration - things like application name, version, database and other settings. The next exercise is to build one such class ApplicationConfiguration. You have to define two class-level methods: set and get. The set method takes two parameters: property_name and value. The get method takes one parameter: property_name, and should return the value that corresponds to the property.

Hint

You can use a Hash to store the key-value pairs.

Output Window

Class variables and inheritance

In the above exercise, you built a single ApplicationConfiguration class that will serve the needs of a single application well enough. But what happens when I have multiple applications and need to store their configuration as well?

The simplest answer is to build new classes, one for each application, and have them inherit from ApplicationConfiguration so that we get the set and get methods. Let us see how that works out:

Example Code:

Output Window

I'm sure you figured out what is going on in here. Even though I have two classes, changes in one affects changes in the other. It also seems that the base class ApplicationConfiguration too is affected when you change anything in any inherited class.

The fact is that any change in any either ApplicationConfiguration, ERPApplicationConfiguration or WebApplicationConfiguration will affect the other two. They all share the same copy of the class variable @@configuration. This is how inheritance of class variables work. But this is not the behavior we want!

The answer to this lies in another type of class variables: class instance variables.

Here is an example of defining a class instance variable and how it works with inheritance:

Example Code:

Output Window

The class instance variable in the above example is @foo. Even though the notation is confusingly similar to a normal instance variable, the difference here is that @foo is initialized directly in the class body and is accessed only from class methods.

As you can see, the values for @foo_count are different for both Foo and Bar. This means that both classes are operating on different @foo_count. Note that we have to initialize @foo_count in all inherited classes.

Now, can you fix our ApplicationConfiguration example to work correctly for both parent and child classes?

Hint

Use class instance variables! Also remember to initialize it in all child classes.

Output Window

Class instance variables are a better alternative than class variables simply because the data is not shared across the inheritance chain. Another major difference between class variables and class instance variables are that class instance variables are available only in class methods. But class variables are available in both class methods and instance methods.

A quick summary before we move on:

  • Instance variables are available only for instances of a class. They look like @name. Class variables are available to both class methods and instance methods. They look like @@name
  • It is almost always a bad idea to use a class variable to store state. There are only a very few valid use cases where class variables are the right choice.
  • Prefer class instance variables over class variables when you do really need store data at a class level. Class instance variables use the same notation as that of an instance variable. But unlike instance variables, you declare them inside the class definition directly.

Congratulations, guest!


% of the book completed

or

This lesson is Copyright © 2011-2014 by Jasim A Basheer