In this article, we’re going to explore the following topics:
- what’s the eigenclass ?
- the eigenclass behind the scene
In Ruby, a class is an object.
In effect, a class is literally an instance of the class Class
.
Feel free to have a look to theShort guide to learning how Classes work in Ruby
article if you’re not familiar with the classClass
.
So, how a class makes the difference between class-level and object-level methods, variables & constants?
By using the eigenclass (a.k.a meta-class, shadow-class, singleton class, etc..).
In Ruby, methods can be called by three ways:
- the method is called by a class:
MyClass.my_method
- the method is called by an object:
my_object.my_method
- with an implicit caller:
puts('puts is an implicit call to self.puts')
By default, when a method is defined in a class then this method becomes an instance method.
This instance method is accessible by all the instances (a.k.a objects) of this class
Here, we can see that the Greeting#hello
method is considered as an instance method.
This method is shared among all the instances of Greeting
.
Now let’s try to add a class method to our Greeting
class
Here the Greeting.hello
method is defined at a class level.
That’s why we can invoke this method by using theGreeting
class as caller.
Also, we can see that the method is defined as a singleton method.
To keep it simple — and related to this article — let’s assume that singleton methods are class methods.
But what if I tell you that a singleton method is also an instance method ?
Well, this makes sense as (almost) everything in Ruby is an object.
What you commonly call a class method is, behind the scene, an instance method of the eigenclass.
By the way, the eigenclass is also referred as singleton class.
Ok.. But what exactly is the eigenclass?
Let’s access the eigenclass and inspect
what it contains
First, we define a Greeting.eigenclass
method.
This method returns self
in the context of the eigenclass — by using the class << self ... end
syntax.
Greeting.eigenclass
returns an instance of the class Class
(a.k.a an anonymous class).
This anonymous class keeps track of the class to which it is attached — the Greeting
class in our case.
Then, we can see that the singleton methods of the Greeting
class are the instance methods of the Greeting
eigenclass.
Note that defining our singleton method usingself.hello
orGreeting.hello
produces the same result.
That’s cool. We now understand what’s the purpose of the eigenclass.
We also know that it’s an anonymous class.
So, now let’s have a deeper look at the properties of this anonymous class.
Let’s detail how the eigenclass is built behind the scene
1- As seen in the previous section, the eigenclass is an unnamed instance of the class Class
.
This anonymous class is defined within Greeting
.
To be certain, we can check the return value of the Module.nesting
method.
This method returns the list of modules & classes nested at the point of call.
2- We can see that the eigenclass inherits from the Object
eigenclass —the #<Class:Object>
.
Indeed, as a class inherits from Object
by default, then it seems natural that a given eigenclass inherits from the Object
eigenclass by default.
Feel free to have a look at theRuby Object Model
article if you’re not familiar with this ancestor chain and theObject
class in Ruby.
The eigenclass tends to be a pretty hard notion to apprehend.
But, in fact, it’s very well designed within the context of Ruby.
Indeed, when you know a bit about Ruby — especially about the Ruby Object Model — the understanding of this notion becomes natural.
In another article, I’ll cover more advanced topics about the eigenclass.
Finally, let’s try to give a proper definition of the eigenclass in Ruby:
The eigenclass is an unnamed instance of the class Class
attached to an object and which instance methods are used as singleton methods of the defined object.
Voilà!