Ruby singleton classes

I was writing some Ruby and I must've had my head stuck in Java, because I wrote something like this:

class Test1
    @x = 1
end

That is very different from this:

class Test2
    def initialize
        @x = 1
    end
end

In the latter case I made a normal instance variable which any object that is_a?(Test2) can access. In the former case I made an instance variable of Test1 itself. Classes in Ruby are Objects like any other; I gave the Test1 object itself an instance variable. So:

Test1.new.instance_variables # => []
Test2.new.instance_variables # => ["@x"]

Chapter 24 of the Pickaxe book talks about singleton classes. You can edit objects (add methods and instance variables etc.) on a per-object basis rather than a per-class basis. You can do this because Ruby makes a "virtual" singleton class, makes that singleton class the direct class of your object, and makes your object's original class the superclass of this new singleton class. That way the object's original class is untouched and your meddling doesn't affect any other objects of the same class.

In Test1 above this is what I did. Ruby made a new singleton class, which the Pickaxe calls 'Test1', and made an instance variable @x in it. That instance variable is then accessible as a part of the Test1 object itself. If it were theoretically possible to instantiate another object of type Test1', it would presumably have a @x too, but this isn't possible.

So say I want to access this @x that belongs to Test1. The Pickaxe tells you how. In general, if you have an object and you want to access an instance variable of it, you define a "getter" method in your object's class that returns the variable's value. You can use the shortcut attr_reader to do this.

So if you want to access an instance variable of Test1 itself, you need to define a method in Test1's class (i.e. the singleton class, Test1'). The Pickaxe says to do this:

class Test1
    class << self
        attr_reader :x
    end
end
 
Test1.x  # =>; 1

It makes perfect sense that you can also do it this way:

class << Test1
    attr_reader :x
end
 
Test1.x  # => 1

The Pickaxe gives a couple reasons why you might want to do this kind of thing. But I'm going to go ahead and label it "black magic" and stay away from it, I think.

Tags: ,

4 Responses to “Ruby singleton classes”

  1. Quoth markus:

    wow

    late but cool
    i never knew this :-)

    btw your << appear wrong in the code

  2. Quoth Brian:

    Oops, must've changed my blog-post bracket-escaping code a while back. I fixed it.

  3. Quoth Peregrinati:

    I'm just learning Ruby now, and I'm struggling with the code:

    class << self
    #…
    end

    that I keep seeing everywhere as I try to learn about singleton and class methods. What does the ‘<<' “Operator” (method?) actually do?

  4. Quoth Brian:

    I'm unsure that << in the case of “class << something” is actually a method. It may be a special operator. Regardless, it's an idiom you pretty much have to memorize. It's not very intuitive at a glance. It means “start a new scope where things inside like def etc. operate on self's singleton class”. A singleton class is a class that applies only to a specific single object. It's also sometimes called a metaclass or any number of other terms.

Leave a Reply

You can use these tags in comments (Note: HTML is automatically escaped inside <pre> tags, nowhere else, so if you post source code, put it in <pre>):

<pre lang="some_programming_language"> 
<em>
<strong>
<a href="url">

NOTE: Comments are automatically spam-filtered. If your comment fails to appear, it was likely munched by the filter. Try not to link-spam or post anything that looks like it was typed by a robot.