Question

I know there have been other questions about the syntax class << self. Still, I did not find those answers clear enough. I have a background in Java/C#, C, so Ruby is kinda strange to me. I read that class << self refers to the singleton class. I find this kinda complex so I would like to understand what does the operator << do in this context and what is possible to put on both ends. I tried to write a simple code to help me understand this syntax (my questions are in the code):

class Self

def Self.selfTest
end

def onSelf
    class << Self   #I know this might be strange. 
        self
    end

end

def onself
    class << self
        self
    end
end

end

s = Self.new
onSelf = s.onSelf
onself = s.onself

#Here, i wanna know what kind of references are returned. 

puts "onSelf responds to onSelf:#{onSelf.respond_to?(:onSelf)}"
puts "onSelf responds to selfTest:#{onSelf.respond_to?(:selfTest)}"
puts "onself responds to onSelf:#{onself.respond_to?(:onSelf)}"
puts "onself responds to selfTest:#{onself.respond_to?(:selfTest)}"

#Output:
#onSelf responds to onSelf:false
#onSelf responds to selfTest:false
#onself responds to onSelf:false
#onself responds to selfTest:true

#So, i conclude that the second one is a reference to a class. What is the first one???????


puts onSelf
puts onself

#Output
#<Class:Self>
#<Class:#<Self:0x007f93640509e8>>

#What does this outputs mean???????

def onSelf.SelfMet
    puts 'This is a method defined on base class'
end


def onself.selfMet
    puts 'This is a method defined on metaclass'
end



puts "Does Self Class respond to SelfMet? : #{Self.respond_to?(:SelfMet)}"
puts "Does Self Class respond to selfMet? : #{Self.respond_to?(:selfMet)}"
puts "Does Self instance respond to SelfMet? : #{s.respond_to?(:SelfMet)}"
puts "Does Self instance respond to selfMet? : #{s.respond_to?(:selfMet)}"

#Output
#Does Self Class respond to SelfMet? : false
#Does Self Class respond to selfMet? : false
#Does Self instance respond to SelfMet? : false
#Does Self instance respond to selfMet? : false

#Why won't they respond to defined methods???? 

Thanks

UPDATED: Thank you all very much. I have read and tested a lot, so will leave a few considerations. I leave this for future reference and as so, i hope the Ruby experts can correct me if i am wrong. I realised that class << Self refers to the Self singleton class. So, the idiomatic class << abcd, starts the abcd singleton class context. I realised also that the hierarchy of a class singleton class is different from an object singleton class. The hierarchy of a class singleton class follows all singleton classes on a hierarchy. In this case:

singleton Self->singleton Object->Singleton basicobject ->class->module->object->kernel->basicObject

The object singleton class lies in a different kind of hierarchy:

Object singleton->Self->Object->kernel->basicObject

This explains this outputs.

Was it helpful?

Solution

In Ruby, every object has a singleton class. This singleton class has only one instance: the object it belongs to.

Since the singleton class has only ever one instance, and every object has its own singleton class, methods that are defined in this class can only be called on that specific object. Those methods are typically called singleton methods, although that is misleading: there's nothing special about those methods, they are just normal standard instance methods.

Here's an example:

foo, bar, baz = Object.new, Object.new, Object.new

class << foo; def quux; :foo end end
class << bar; def quux; :bar end end

foo.quux # => :foo
bar.quux # => :bar
baz.quux # NoMethodError

Classes are just objects like any other object. So, just like any other object, they have singleton classes. Methods defined in the singleton class of an object that happens to be a class are typically called class methods, although again, there's nothing special about them, they are just singleton methods of an object which happens to be a class, which in turn means they are just regular instance methods of a singleton class which belongs to an object which happens to be a class.

So, if you compare this to something like Java, you can see a duality: in Java, there is only one kind of class but there are two kinds of methods (instance and static). In Ruby, there is only one kind of method (instance) but it can be defined in different kinds of classes (regular and singleton).

I find this kinda complex so I would like to understand what does the operator << do in this context

That's just the syntax for opening up a singleton class as opposed to opening up a class.

and what is possible to put on both ends.

Well, on the left has to be the keyword class and on the right any expression that returns an object.

OTHER TIPS

Perhaps this will help. If you add the following statements you will get the indicated results:

puts onSelf                         #=> #<Class:Self> 
puts Self.singleton_class           #=> #<Class:Self>
puts onSelf == Self.singleton_class #=> true

puts onself                         #=> #<Class:#<Self:0x007fe6330aab10>>
puts s.singleton_class              #=> #<Class:#<Self:0x007fe6330aab10>>
puts onself == s.singleton_class    #=> true

I see no point in defining a method whose receiver is a metaclass, but that is what you have done:

puts onSelf.SelfMet
  #=> This is a method defined on Self's metaclass

puts onself.selfMet
  #=> This is a method defined on s's metaclass

Obviously, onSelf (Self.singleton_class) responds to SelfMet (but not to selfmet), and onself (s.singleton_class) responds to selfmet (but not to Selfmet).

For Self to respond to SelfMet, the latter would have to be defined def Self.SelfMet... or def self.SelfMet.. (or one of a few other ways), but it is not.

Similiarly, for s to respond to selfMet, the latter would have to be defined as a normal instance method def selfMet... (in which case all other instances of Self would also respond to it) or defined in s's singleton class: def s.selfMet... (in which case other instances of Self would not respond to it).

In sum, the class Self responds to its singleton methods, as does the instance s respond to its singleton methods; the singleton classes of Self and s do not respond to those respective singleton methods.

The following may help you understand what's going on here. Each p self followed by #=> displays what follows #=> when the statement is executed by Ruby. Notice how the various statements, such as class Dog, class << self and others are used to change the value of self to what we want. p self is your best friend when metaprogramming.

p self            #=> main

class Dog
  p self          #=> Dog

  def self.woof1
    p self
  end

  def Dog.woof2
    p self
  end

  p self          #=> Dog

  class << self
    p self                #=> #<Class:Dog>
    p Dog.singleton_class #=> #<Class:Dog>  
    def woof3
      p self
    end
  end

  p self          #=> Dog

  def woof4
    p self
  end
end

p self            #=> main

def Dog.woof5
  p self
end

Dog.instance_eval do
  p self          #=> Dog
  def woof6
    p self
  end
end  

dog = Dog.new     #=> #<Dog:0x007fe17b08cf00> 

def dog.woof7
  p self
end

dog.instance_eval do
  p self          #=> #<Dog:0x007fe17b08cf00>
  def woof8
    p self
  end
end  

p self            #=> main

Dog.woof1 #=> Dog
Dog.woof2 #=> Dog
Dog.woof3 #=> Dog
Dog.woof5 #=> Dog
Dog.woof6 #=> Dog

dog.woof4 #=> #<Dog:0x007fe17b08cf00>
dog.woof7 #=> #<Dog:0x007fe17b08cf00>
dog.woof8 #=> #<Dog:0x007fe17b08cf00>

puppy = Dog.new #=> #<Dog:0x007fe17ba93a08>
puppy.woof4     #=> #<Dog:0x007fe17ba93a08>
puppy.woof7 #=> undefined method `woof7' for #<Dog:0x007fe5fb3e1d48>
puppy.woof8 #=> undefined method `woof8' for #<Dog:0x007fe5fb3e1d48>

It takes awhile to sort everything out. Even then, most of us need a refresher from time-to-time. Here's an excellent article on the subject. Also, look at some of the references in the comments there, especially Dave Thomas' presentation.

Lastly, have a look at Ruby's naming convention.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top