26
What does "class << self" actually do in Ruby?
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
Now hello
method can be called on the Greeting
class.
>> 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 Object
.
>> 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
class.
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!
So, 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 << obj
block will be added to theobj
object. -
obj
can 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
I hope now you see that all class methods(no matter whether they are defined using class << self
or def self.method
syntax) are actually instance methods of the singleton class of the class object.
-
class << obj
block 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
#singleton_class
method 😎
26