Apr 09, 2007 @ 02:42 pm

First of all, let’s go back to the basics. What we generally call a class method is a method that resides at the class level. On the opposite, an instance method is a method that resides at the object level.

#UPDATE 2007/04/15
I changed the previous paragraph and removed the word ’shared’ when talking about class methods because it was confusing. A class method isn’t ’shared’ since it’s instances cannot access it without using explicitly the reference to the class, like that : my_obj.class.class_method. And no, unlike someone have suggested, the super keyword won’t work. I’ve just been too quick to update my post… sorry)
END UPDATE

In ruby, classes are also objects, so the methods you define as class methods only exist in the object that defined them (the class) and nowhere else. If you define my_class_method in a class named Test, my_class_method will only live into the object Test, which is an instance of a built-in ruby class named Class. If what I just said sounded like mandarin, you might want to read this post first.

Every instances that you create contain a variable that points to their corresponding class. Say you create a new instance of class Test and that you name this instance x (x = Test.new). x will contain every instance variables/methods that have been defined as such in the class as well as a reference to the object Test, which will contain the variables that need to be shared among every instances of this class (class variables) as well as methods that will be local to this object (class methods). That’s the reason why ruby complain when you write something like x.my_class_method. It complains because my_class_method just doesn’t reside in x, it resides in Test.

You have 2 ways for defining a class method.

1) You can use the name of the class directly

  1. class Test #Test is now an instance of a built-in class named Class
  2.   def Test.class_method
  3.     "I’m a class method."
  4.   end
  5. end

2) You can use the self variable, which is always pointing to the current object

  1. class Test
  2.   def self.class_method
  3.     "I’m a class method."
  4.   end
  5. end

Once you understand that classes are objects, this use of the self variable to define a class method finally makes sense.

In fact, there is another way to define a class method. I personally find it a little bit more obscure. it consists of building a new anonymous class only for the current object (self). To create the anonymous class, we use the << notation.

  1. class Test
  2.   def some_method
  3.     "bla bla bla"
  4.   end
  5.  
  6.   class <<self
  7.     def my_class_method1
  8.         "Weirdo"
  9.     end
  10.  
  11.     def my_class_method2
  12.         "But use it if you want"
  13.     end
  14.   end
  15. end

Remember what we have to do to add a new instance method in a class :

  1. class Test
  2.   def hello
  3.     "Hello! I’m an instance method"
  4.     "I’m accessible in every single instance of class Test"
  5.   end
  6. end
  7.  
  8. x = Test.new
  9. #Add a new method to an instance of class Test
  10. def x.goodbye
  11.   "Goodbye! I’m an instance method"
  12.   "I only exists in x"
  13. end

When you look at it, it’s exactly the same trick that we previously used to add a new class method. The only difference is that instead of adding a method to an instance of class Class, we added a method to an instance of class Test.

The value of self

Not too surprinsingly, when you are inside a class method, the value of self refers to the object that holds the class structure (the instance of class Class). This means that :

  1. class Test
  2.   def self.class_method
  3.     self.x
  4.   end
  5. end

is equivalent to :

  1. class Test
  2.   def self.class_method
  3.     Test.x
  4.   end
  5. end

When you are inside an instance method, the value of self still refers to the current object. This time however, the current object is an instance of class Test, not an instance of class Class.

#UPDATE (10/31/2007)
The rest of this post was not relevant, a bit confusing and just not accurate enough for my taste. Thus, it has been removed!

Bookmark this post : These icons link to social bookmarking sites where readers can share and discover new web pages.
  • DZone
  • Reddit
  • del.icio.us
  • Digg
  • Furl
  • Technorati
  • StumbleUpon
Rate this post :
1 Star2 Stars3 Stars4 Stars5 Stars (3 votes, average: 5 out of 5)
Loading ... Loading ...
Posted under : In depth
6 Comments
MyAvatars 0.2

‘A class method isn’t ’shared’ since it’s instances cannot access it.’

This isn’t actually true. An instance can access a class method via super. Like so:

self.super.class_method

Comment by : Mr eel
— April 11, 2007 @ 9:19 pm

MyAvatars 0.2

Hmmm… I should have check your code before actually update my post (I’m learning how to blog everyday). You cannot access a class method the way you have indicated. super is for super classes, not for class methods.

Comment by : Frank
— April 11, 2007 @ 9:52 pm

MyAvatars 0.2

Great post, as usual, Fleebie.

I was aware that I could define class methods using:

def self.class_method

But I didn’t know about:

def Test.class_method

I will start using the second method because it is a lot clearer to me.

Comment by : Clinton Forbes
— April 11, 2007 @ 9:53 pm

MyAvatars 0.2

Thanks Clinton,

I also prefer to use Test.class_method over self.class_method. It just feels more natural and intuitive to me.

Comment by : Frank
— April 13, 2007 @ 9:39 am

MyAvatars 0.2

Most Ruby coders actually prefer self.class_method to Test.class_method. The main rationale is that Test.class_method violates the “Don’t Repeat Yourself” principle - you’re repeating the name of the class in different places. If the name changes, you’ll have to change it into all class methods definition.

As with all matters of style, YMMV.

Comment by : Paolo Perrotta
— April 18, 2007 @ 8:34 pm

MyAvatars 0.2

these basic are really useful to me to understand the class methods especially example with the notation “

Comment by : sadeesh
— June 6, 2008 @ 10:31 pm




Leave a comment
Name (required)
Email (will not be publish) (required)
Website