6

I was trying to limit the instantiation of a class to just a single one(without using singleton) but i couldn't. I tried with class variables (@@) but without luck. I googled it and came across this:

class A 
  @count = 0 

  class << self 
    attr_accessor :count 
  end

  def initialize val 
    @a = val 
    self.class.count += 1 
  end 
end 

a=A.new 42 
b=A.new 43

I searched for the 'class << self' explanation hoping to find a better(or just a more simple and clean) but againt, no luck. Finally, after some tests i concluded that 'class << self' is just a block wrapper where you can define class methods. So, is this the correct?

Regards!

John Topley
  • 113,588
  • 46
  • 195
  • 237
fk2blow
  • 155
  • 1
  • 10
  • Your first sentence doesn't really make sense because if your class can only have one instance then it's a singleton, regardless of how you implement that behaviour. Or did you mean the singleton class (eigenclass)? – John Topley Jan 08 '10 at 08:45
  • @John, im assuming he means the `Singleton` class included in the standard lib. – horseyguy Jan 08 '10 at 09:07

4 Answers4

38

The class << self notation opens up the eigenclass of an object. An eigenclass is an anonymous class that stores instance-specific behaviour. In the case of a class an eigenclass is sometimes called a metaclass.

Ruby uses eigenclasses to implement so called 'class methods' (also called static methods).

A Class (as moritz stated) is also an Object in Ruby and in so far as it is an object it also has a class. The class of a class in Ruby is called Class.

A 'class method' in any language is a method in which a class is the receiver - that is the method is directly invoked on the class itself.

However in order for a method to be invoked on a receiver that method must be defined on the class of that receiver. In the case of classes a 'class method' could be implemented as an instance method on the Class class.

But defining an instance method on Class would mean that ALL classes get access to that class method which is not ideal.

Enter the eigenclass, as stated before, the eigenclass for an object is a special class that stores the methods unique to that object. In the case of classes the eigenclass subclasses the Class class and is the direct class of the class.

'class methods' in Ruby therefore are just 'instance methods' defined on the class's eigenclass.

The def MyClass.my_method notation actually defines my_method on the eigenclass of MyClass. If you use this notation you can get by (for a while) without actually understanding eigenclasses since you can trick yourself into thinking it is just Ruby's way of defining 'static methods' and continue thinking Ruby's class model is similar to Java's. However, the class << self notation allows no such interpretation and you must come to terms with the reality of eigenclasses.

In summary, 'class methods' are actually 'instance methods' defined on the eigenclass and the class << self gives you access to the eigenclass.

For more reading check out these links:

http://banisterfiend.wordpress.com/2008/11/25/a-complete-ruby-class-diagram/

http://banisterfiend.wordpress.com/2008/10/25/the-secret-life-of-singletons/

http://www.klankboomklang.com/2007/09/21/the-singleton-class/

horseyguy
  • 29,455
  • 20
  • 103
  • 145
  • Great explanation -- I was googling the class << self syntax and now I understand the whole class structure. Thanks! – csjacobs24 May 07 '15 at 16:53
  • 1
    Here's a related question: what happens when you define a method with `self.method_name` INSIDE the eigenclass (i.e. within a `class << self` block). Where does that method end up? I'm not asking if it's a good idea, or even recommended... just was curious what object it ends up on. – GuyPaddock Feb 02 '18 at 14:55
  • 2
    I wanted to know the answer to @GuyPaddock's question. Using `class << self` within `class << self` does indeed put you in the eigenclass _of the eigenclass_, demonstrating how internally consistent Ruby is. Since an eigenclass' is `instance_of?(Class)`, it has the `singleton_class` method available. Thus we can define singleton classes on singleton classes on singleton classes on... – Tomboyo Jul 11 '18 at 02:37
  • You can test this with `eigenclass = class Dog; class << self; self; end; end` and `eigen_eigenclass = class Dog; class << self; class << self; self; end; end; end`. Note that `eigenclass != eigen_eigencalss #=> true` and `eigenclass.singleton_class == eigen_eigenclass #=> true`. – Tomboyo Jul 11 '18 at 02:39
5

Technically, you're defining a method on the metaclass of the class, rather than the class itself. Yehuda Katz has a great explanation of metaclasses in Ruby here: http://yehudakatz.com/2009/11/15/metaprogramming-in-ruby-its-all-about-the-self/

kejadlen
  • 1,519
  • 1
  • 10
  • 10
  • _why also wrote a good article about it: http://ruby-metaprogramming.rubylearning.com/html/seeingMetaclassesClearly.html – kejadlen Jan 08 '10 at 06:33
3

The subject line doesn't quite match the body of the question. I'm going to address the question expressed in the subject line:

They are synonymous.

def self.foo
    ...
end

is just shorthand for

class << self
    def foo
        ...
    end
end
Noach Magedman
  • 2,313
  • 1
  • 23
  • 18
2

Your conclusion is right. Basically, you have to keep in mind that even classes are objects in ruby, and therefore, have instances. And with the class << self statement you are just altering that class instance of your object.

moritz
  • 2,448
  • 1
  • 20
  • 25
  • I've just revised the '<<' operator from the string class. I feel so dumb now. It just concatenates the string 'class' with the name of the class - 'self', just like i did when i declared the class din the first place. I got it now. Thank you very much! – fk2blow Jan 08 '10 at 05:02
  • 1
    wtf? This explanation is totally bizarre. You say that "classes are objects in ruby, and therefore, have instances", I think you mean to say that classes ARE instances? Since it is no surprise that a class _has_ instances (that is the nature of a class). Further you say the "class << self" allows you to alter the 'class instance of your object'. Wtf? what does this even mean. I'm sorry the terminology in this answer is just too weird and I think it demonstrates an incomplete understanding. – horseyguy Jan 08 '10 at 06:05
  • classes are instances? I'm not so sure about who has an incomplete understanding. Would be helpful if you would take the time to provide a less bizarre answer to help me get it right next time. – moritz Jan 08 '10 at 06:23
  • 1
    Take a look at the link I provided in my answer for a thorough understanding of what actually happens when you do "class << self". – kejadlen Jan 08 '10 at 06:25
  • @mortiz, answer below. And yes, classes are instances (instances of Class and of their metaclass) ;) – horseyguy Jan 08 '10 at 06:54