As a ruby developer, you almost certainly have seen
class << self definition inside a class. Methods defined within
class << self block become class methods. Here's an example.
class Greeting class << self def hello puts "Hello!" end end end
hello method can be called on the
>> Greeting.hello Hello!
You can also add a class method like this.
class Greeting def self.hello puts "Hello!" end end
The end result will be the same. Does it mean that
class << self is simply a syntactic sugar that allows adding class methods? Not exactly. To understand what
class << self actually does, we must first understand what
self is inside a class.
There's always a
self object at any point in the Ruby code. Outside of any class/module/method definitions,
self is a
main object of the class
>> puts self, self.class main Object
Inside a method within a class,
self is the object of that class.
class Greeting def whoami puts self, self.class end end
>> Greeting.new.whoami #<Greeting:0x00007ff03c8f6e78> Greeting
And, within a class but outside of any method,
self is the class object. In Ruby, classes are objects too. Every class is an object of the
class Greeting puts self # Greeting puts self.class # Class end
Now that we know that
self is simply a class object, let's try to replace it with the actual class name and see how that works.
class Greeting class << Greeting def hello puts "Hello!" end end end
Works like a charm 😎
>> Greeting.hello Hello!
class << Greeting is that same as
class << self. Methods inside that block get added to the
Greeting class object. But wait, since
Greeting is an object, can we replace it with any other object? Can we use a non-class object? Let's try.
obj = Object.new class << obj def hello puts "Hello!" end end
>> obj.hello Hello!
Turns out that
class << ... doesn't necessarily have to be used with class objects. You can use it with any object.
So far we learned that:
- Method defined within
class << objblock will be added to the
objcan be any object.
class << self definition is used often within a class, that new Ruby developers might think that it's some kind syntactic sugar available only for classes which allows to add class methods. But now we know that it's not true.
There's one more thing worth mentioning.
class << obj block opens a singleton class. Every Ruby object has a singleton class. Methods defined within
class << obj block are instance methods of the singleton class of the object
obj 🤯 The most important thing to remember is that singleton class instance methods take precedence in the method lookup process. This example should explain more.
class Greeting def hello puts "Hello!" end end obj = Greeting.new class << obj def hello puts "Hola!" end end
>> obj.hello Hola!
Singleton class is a regular class object which you can access using
#singleton_class method. This method is available for all objects.
>> puts obj.singleton_class, obj.singleton_class.class #<Class:#<Object:0x00007faf18146648>> Class
Since it's just a class, you can list its instance methods.
# Let's add one more method for the sake of example. class << obj def hola puts "Hola!" end end
>> obj.singleton_class.instance_methods(false) => [:hola, :hello]
The last thing I'd like to mention about the singleton class is that you can also define its instance methods using this syntax.
def obj.hello puts "Hello!" end
class << objblock opens a singleton class 🙃
- In that block we can defined instance methods of the singleton class 🧐
- Those methods take precedence in the method lookup process 🚀
- Singleton class is a regular class object 😁
- Every Ruby object has its own singleton class which can be accessed via