In Progress
Unit 1, Lesson 21
In Progress

class<

Have you ever seen some Ruby code that looks like this?

class <<self
# ...
end

This is one of Ruby’s stranger syntactical idioms, and you might have wondered what it accomplishes. Or perhaps you’ve pondered why some codebases seem to use it a lot, while others don’t use it at all.

In this episode from the freezer, you’ll learn more about the meaning of this syntax, as well as about why it’s not always the best choice for defining singleton methods.

Video transcript & code

In Ruby as in most OO languages, classes can have both class-level and instance-level methods. We typically define class-level methods with def self. and then the method name.

class C
  def self.foo
    puts "Who needs instances, I'm a class method!"
  end
end

C.foo
# >> Who needs instances, I'm a class method!

This syntax looks pretty odd if you're new to the language. It makes more sense once you realize what's going on. In Ruby we can attach a method to any object by writing def, then the object we want to stick the new method on, then a dot, and then the method name. Here we're attaching a new method to a String object.

s = "Bob"

def s.greet
  puts "Hi I'm #{self}"
end

s.greet
# >> Hi I'm Bob

In technically terms what we're doing here is inserting the new method into the object's singleton class - the special anonymous class that contains any methods which are defined for just that one instance.

In Ruby classes are objects too, and inside a class declaration, the self object is simply the class currently being defined. So when we say def self.foo, we're saying "attach this new method to the current class object".

class MyClass
  puts "Hello from #{self}"
end

# >> Hello from MyClass  

It's even easier to see what's going on with class method definitions when we use another style that used to be more common than it is now. In this style we explicitly specify the class name instead of using self.

class C
  def C.foo
    puts "Who needs instances, I'm a class method!"
  end

  def C.bar
    puts "I'm a class method too!"
  end
end

This makes it clearer that we're just tacking a method onto the class object. But this style has gone out of fashion, and I think for good reason. Repeating the class name is unnecessary duplication and is just one more thing to have to rewrite if we ever change the name of the class.

Yet another style that has become more common in recent years looks rather different. Rather than using singleton method syntax, we use the class << self syntax to open up a window into the class object's singleton class. If this sounds convoluted, well, it still hurts my head a little too. But the upshot is that we can define methods as if they are ordinary instance methods in this context, and they will show up on the class object.

class C
  def self.foo
    puts "Who needs instances, I'm a class method!"
  end

  def C.bar
    puts "I'm a class method too!"
  end

  class << self
    def baz
      puts "Just another class method"
    end
  end
end

C.baz
# >> Just another class method

One argument in favor of this style is that it requires less typing, since we don't have to prefix each class method name with self.. Another is that if we want to change a class-level method to instance-level or vice-versa, we can simply cut and paste it into the appropriate section.

The downside is that if the class has more than a few short class methods, it can be easy to lose track of whether you're looking at a class method or an instance method since there's nothing to visually flag the individual methods as class-level.

class C
  class << self
    def foo
      puts "Who needs instances, I'm a class method!"
    end

    def bar
      puts "I'm a class method too!"
    end

    def baz
      puts "Just another class method"
    end
  end
end

C.baz
# >> Just another class method

This is a significant drawback, in my experience. On numerous occasions I've observed programmers waste a lot of time trying to figure out why their changes weren't taking effect, only to realize they were editing a class-level method instead of the instance method they thought they were in. This group of often-confused coders includes myself. In my opinion this fact strongly outweighs any negligible savings in number of characters typed, or in moving methods around. As a result I don't recommend using the class << self style of class method definition.

To tie this episode in with the preceding one: I see the self. preceding each class method as coincidental duplication. It may be repetitive, but it's individually meaningful for each method, rather than an implementation detail they all share. And it's an important visual tag to the reader.

That's all for now. Happy hacking!

Responses