Unraveling Classes, Instances and Metaclasses in Ruby
Tags: ruby, programming, beginners
Published: 2019-02-05 13:57:50

---
title: Unraveling Classes, Instances and Metaclasses in Ruby
description: Through examining metaclasses, we'll learn how class and instance methods work in Ruby.
cover_image: https://blog.appsignal.com/images/blog/2019-02/unraveling-metaclasses.jpg
tags: ruby, programming, beginners
published: true
canonical_url: https://blog.appsignal.com/2019/02/05/ruby-magic-classes-instances-and-metaclasses.html
---

Welcome to a new episode of Ruby Magic! This month's edition is all about metaclasses, a subject sparked by a discussion between two developers (Hi Maud!).

Through examining metaclasses, we'll learn how class and instance methods work in Ruby. Along the way, discover the difference between defining a method by passing an explicit "definee" and using `class << self` or `instance_eval`. Let's go!

## Class Instances and Instance Methods

To understand why metaclasses are used in Ruby, we'll start by examining what the differences are between instance- and class methods.

In Ruby, a *class* is an object that defines a blueprint to create other objects. Classes define which methods are available on any instance of that class.

Defining a method inside a class creates an *instance method* on that class. Any future instance of that class will have that method available.

``` ruby
class User
  def initialize(name)
    @name = name
  end

  def name
    @name
  end
end

user = User.new('Thijs')
user.name # => "Thijs"
```

In this example, we create a class named `User`, with an *instance method* named `#name` that returns the user's name. Using the class, we then create a *class instance* and store it in a variable named `user`. Since `user` is an instance of the `User` class, it has the `#name` method available.

A class stores its instance methods in its *[method table](https://en.wikipedia.org/wiki/Virtual_method_table)*. Any instance of that class refers to its class’ method table to get access to its instance methods.

## Class Objects

A *class method* is a method that can be called directly on the class without having to create an instance first. A class method is created by prefixing its name with `self.` when defining it.

A class is itself an object. A constant refers to the class object, so class methods defined on it can be called from anywhere in the application.

``` ruby
class User
  # ...

  def self.all
    [new("Thijs"), new("Robert"), new("Tom")]
  end
end

User.all # => [#<User:0x00007fb01701efb8 @name="Thijs">, #<User:0x00007fb01701ef68 @name="Robert">, #<User:0x00007fb01701ef18 @name="Tom">]
```

Methods defined with a `self.`-prefix aren’t added to the class’s method table. They’re instead added to the class’ metaclass.

## Metaclasses

Aside from a class, each object in Ruby has a hidden metaclass. Metaclasses are singletons, meaning they belong to a single object. If you create multiple instances of a class, they’ll share the same class, but they’ll all have separate metaclasses.

``` ruby
thijs, robert, tom = User.all

thijs.class # => User
robert.class # => User
tom.class # => User

thijs.singleton_class  # => #<Class:#<User:0x00007fb71a9a2cb0>>
robert.singleton_class # => #<Class:#<User:0x00007fb71a9a2c60>>
tom.singleton_class    # => #<Class:#<User:0x00007fb71a9a2c10>>
```

In this example, we see that although each of the objects has the class `User`, their singleton classes have different object IDs, meaning they’re separate objects.

By having access to a metaclass, Ruby allows adding methods directly to existing objects. Doing so won’t add a new method to the object’s class.

```ruby
robert = User.new("Robert")

def robert.last_name
  "Beekman"
end

robert.last_name # => "Beekman"
User.new("Tom").last_name # => NoMethodError (undefined method `last_name' for #<User:0x00007fe1cb116408>)
```

In this example, we add a `#last_name` to the user stored in the `robert` variable. Although `robert` is an instance of `User`, any newly created instances of `User` won’t have access to the `#last_name` method, as it only exists on `robert`’s metaclass.

## What Is `self`?

When defining a method and passing a receiver, the new method is added to the receiver’s metaclass, instead of adding it to the class’ method table.

``` ruby
tom = User.new("Tom")

def tom.last_name
  "de Bruijn"
end
```

In the example above, we've added `#last_name` directly on the `tom` object, by passing `tom` as the receiver when defining the method.

This is also how it works for class methods.

``` ruby
class User
  # ...

  def self.all
    [new("Thijs"), new("Robert"), new("Tom")]
  end
end
```

Here, we explicitly pass `self` as a receiver when creating the `.all` method. In a class definition, `self` refers to the class (`User` in this case), so the `.all` method gets added to `User`'s metaclass.

Because `User` is an object stored in a constant, we’ll access the same object—and the same metaclass—whenever we reference it.

## Opening the Metaclass

We’ve learned that class methods are methods in the class object’s metaclass. Knowing this, we’ll look at some other techniques of creating class methods that you might have seen before.

### `class << self`

Although it has gone out of style a bit, some libraries use `class << self` to define class methods. This syntax trick opens up the current class's metaclass and interacts with it directly.

``` ruby
class User
  class << self
    self # => #<Class:User>

    def all
      [new("Thijs"), new("Robert"), new("Tom")]
    end
  end
end

User.all # => [#<User:0x00007fb01701efb8 @name="Thijs">, #<User:0x00007fb01701ef68 @name="Robert">, #<User:0x00007fb01701ef18 @name="Tom">]
```

This example creates a class method named `User.all` by adding a method to `User`'s metaclass. Instead of explicitly passing a receiver for the method as we saw previously, we set `self` to `User`'s metaclass instead of `User` itself.

As we learned before, any method definition without an explicit receiver gets added as an instance method of the current class. Inside the block, the current class is `User`'s metaclass (`#<Class:User>`).

### `instance_eval`

Another option is by using `instance_eval`, which does the same thing with one major difference. Although the class's metaclass receives the methods defined in the block, `self` remains a reference to the main class.

``` ruby
class User
  instance_eval do
    self # => User

    def all
      [new("Thijs"), new("Robert"), new("Tom")]
    end
  end
end

User.all # => [#<User:0x00007fb01701efb8 @name="Thijs">, #<User:0x00007fb01701ef68 @name="Robert">, #<User:0x00007fb01701ef18 @name="Tom">]
```

In this example, we define an instance method on `User`'s metaclass just like before, but `self` still points to `User`. Although it usually points to the same object, the "default definee" and `self` can point to different objects.

## What We've Learned

We've learned that classes are the only objects that can have methods, and that instance methods are actually methods on an object's metaclass. We know that `class << self` simply swaps `self` around to allow you to define methods on the metaclass, and we know that `instance_eval` does mostly the same thing (but without touching `self`).

Although you won't explicitly work with metaclasses, Ruby uses them extensively under the hood. Knowing what happens when you define a method can help you understand why Ruby behaves like it does (and why you have to prefix class methods with `self.`).

Thanks for reading. If you liked what you read, you might like to [subscribe to Ruby Magic](https://blog.appsignal.com/ruby-magic) to receive an e-mail when we publish a new article about once a month.