👨‍💻 I'm in search of a remote Ruby/Rails Developer position. Hire me.

The Real Difference: obj.method_name vs class << obj.Photo by Will Francis

I was looking at some answers on StackOverflow for the difference between Ruby’s self.method_name and class << self. I wasn’t satisfied with the answers. While all the answers did very well at explaining object.method_name and class << object, I feel none stated the difference sought after. This is to complement these answers on how they differ.

What’s noteworthy.

To me, the difference betweenobject.method_name and class << object that’s worth propagating would be how both notations resolve constants. Let’s go through an example.

Let’s assume we have a program like this:

FLIGHT_NUMBER = "QTR1"

aircraft = Object.new

class << aircraft
  FLIGHT_NUMBER = "QTR5"
end

In our short program, we have two constants both named FLIGHT_NUMBER, but with different values. Note how we’re setting the last constant inside of aircraft’s anonymous (singleton) class.

With the above let’s use both notations to define singleton methods and call these methods:

def aircraft.print_flight_no
  puts FLIGHT_NUMBER
end

class << aircraft
  def show_flight_no
    puts FLIGHT_NUMBER
  end
end

aircraft.print_flight_no
aircraft.show_flight_no

This returns:

QTR1
QTR5

As stated concisely by a Redditor:

When you write def object.method_name, you are defining a method in the specified object’s eigenclass, but not changing the default ‘definee’ or the ‘cref’ within the body of that method.

When you write class << object, you are updating both the default ‘definee’ and the ‘cref’ with the object’s eigenclass, until the end of the class definition.

– Flimsy_Pomelo

There are some rare elaborations in the depths of the internet on this subject.

The visibility of our constants is affected by the notation we pick. In general, the apparent implications of both notations are similar. You pick one over the other if scoping and grouping of class methods are what matter to you.

Different notations. Different reactions.

Like you already know, everything (almost) in Ruby is an object. These objects can have singleton methods attached to them except for the subclasses of the Numeric class: Complex, Rational, Float and Integer.

These class react differently to obj.method_name and class << obj. Here’s an example:

class << Complex(1)
  def hi
    "hey!"
  end
end

This will output something like:

can't modify frozen object: 1+0i (FrozenError)

Doing this:

int = 5

class << int
  def hi
    "hey!"
  end
end

# OR

def int.hi
  "hey!"
end

will output:

can't define singleton (TypeError)

Subclasses of the Numeric class behave differently to both ways of defining singleton methods on them. This shouldn’t be considered a real difference, but it doesn’t hurt knowing that descendants of Numeric can’t have singleton methods on their instances.

#StayHome. Stay safe.