tags:

views:

115

answers:

4

How is this explained? Can I replace self with some other object?

+10  A: 

This syntax is used in ruby to access an object's metaclass, or singleton class. The metaclass is used to store methods for an individual object.

obj = # whatever...
class <<obj
  # here, self is defined as obj's metaclass
  # so foo will be an instance method of obj's metaclass
  # meaning that we can call obj.foo
  def foo
    # ...
  end
end
# this is equivalent to the above
def obj.foo
  # ...
end

This is a core part of the language, and isn't defined in any library.

rampion
+2  A: 

You use that syntax to add class methods, which you call on the class, instead of on a particular instance of that class.

For example:

  class Foo
    class << self
      def do_foo
        # something useful
      end
    end
  end

Now you can call Foo.do_foo even if you don't have an object of type Foo.

This is equivalent:

  class Foo
    def self.do_foo
      # something useful
    end
  end
Sarah Mei
+4  A: 

Also see _why's explanation of metaclasses:

http://whytheluckystiff.net/articles/seeingMetaclassesClearly.html

Also regarding "self" and replacing it, I've seen this mentioned a few other places - it's difficult for me to think of a good use-case for that feature, though it would sure confuse me. Perhaps there is one. In any case, it is invalid syntax in Ruby to try to change the value of "self":

>> self = Object.new
SyntaxError: compile error
(irb):1: Can't change the value of self
self = Object.new
     ^
from (irb):1
from :0

In Ruby, and in all other languages that have this concept of "self" or "this", it's used as a pointer to "here", as in, this current object, or class, or metaclass, or whichever object represents what "here" means. Since Ruby is interpreted line-by-line, "self" means the enclosing object when the compiler encounters that keyword.

class Array
  self # Means Array class (which is an object, actually)

  def self.class_method
    self # still means Array class, since you're in a class method
  end

  def hello
    self # Means the current instance of Array
  end

  class << self
    self # Means the metaclass (or "eigenclass") of the Array
  end
end
Colin Curtin
I think jtr meant use a different object, other than self in the `class <<` syntax, not reassign self to a different object. But the phrasing isn't perfectly clear. +1 for citing _why - his entry helped me learn a lot of this in the first place.
rampion
Ah. That makes more sense, thank you. :)
Colin Curtin