Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the purpose of the "class << Class" (angle brackets) syntax?

Tags:

syntax

class

ruby

Why would I want to add anything to a class using class << Class syntax?

class Fun
    def much_fun
        # some code here
    end
end

class << Fun # the difference is here!
    def much_more_fun
        # some code here
    end
end

instead of using the monkey patching/duck punching method:

class Fun
    def much_fun
        # some code here
    end
end

class Fun # the difference is here!
    def much_more_fun
        # some code here
    end
end

While reading Why's Poignant Guide to Ruby I came across:

Why defines a class LotteryDraw:

class LotteryDraw
    # some code here
    def LotteryDraw.buy( customer, *tickets )
        # some code here as well
    end
end

and after a while adds a method to the LotteryDraw class:

class << LotteryDraw
    def play
        # some code here
    end
end

saying that:

When you see class << obj, believe in your heart, I’m adding directly to the definition of obj.

What is the purpose of this syntax? Why did Why decide to do it this way instead of using the monkey patching method?


These are some related questions and websites:

  • Adding a new method to the Array class
  • Yield in class << self in class method, which gives me a little bit of an idea why I would like to use class << Class syntax.
  • Open Classes in Ruby
like image 810
Mateusz Piotrowski Avatar asked Oct 31 '15 15:10

Mateusz Piotrowski


1 Answers

A little more explanation is needed. In ruby almost every single object can create a weird thing called an instance class. This thing is just like a normal class, the main difference is that it has only one single instance and that that instance is created before that class.

In short, having class A, you can do:

a = A.new
b = A.new

Both, a and b are now the instances of class A and have an access to all the instance method defined within this class. Now let's say, we want to add an extra method which can only be accesses by a, but not by b (this might be useful in some cases, but rather avoid it if possible). All the methods are defined within the classes, so it seems we need to add it to class A, but this way it will be accessible by b as well. In this case we need to create an instance class for a object. To do that, we use class << <object> syntax:

class << a
  def foo
  end
end

a.foo #=> nil
b.foo #=> undefined method

In short, class << <object> opens an instance class for given object, allowing to define additional instance methods for given instance, which will not be available on any other objects.

Now, with that being said: in Ruby, classes are jest instances of class Class. This:

class A
end

Is almost equivalent to (differences not important here)

A = Class.new

So if classes are objects, they can create their instance classes.

class << A
  def foo
  end
end

A.foo  #=> nil
Class.new.foo #=> undefined method

It is commonly used to add so-called class method to given class, the point however is that in fact you are creating an instance method on class' instance class.

like image 111
BroiSatse Avatar answered Oct 09 '22 10:10

BroiSatse