1

I continue my study on Ruby and another question occurred me. I know that when we define a class method on a class, it's created a singleton class that gets the definition of that method, and from then on, that method is an instance method of that singleton class(i got this conclusion from tests, but i might be wrong, so feel free to correct me).

My question is, how can i call a class method on a class X with X.classMethod if the method is defined on a singleton class as an instance method of that class(i am not asking how can i do it. It is what happens.). It confuses me even more, because i noticed(running some tests) that the singleton class of a class is not even hierarchically related to the class it comes from, so, how is a class method call resolved to the singleton class? And more precisely: how is the class calling a method on a singleton class that is an instance method, without any instance.

I hope i did not confuse you.

Thanks you once more.

quetzalcoatl
  • 32,194
  • 8
  • 68
  • 107
BrunoMCBraga
  • 652
  • 2
  • 7
  • 23

2 Answers2

2

I would start with a below example :

class Foo
  def self.bar
    puts 12
  end
end

Foo.singleton_methods # => [:bar]
Foo.ancestors # => [Foo, Object, Kernel, BasicObject]

In Ruby class(s) are also objects. Now here #bar is a singleton method of Foo. When you did Foo.bar, Foo first searched in its singleton class, then up the ancestor chains singleton class. singleton class are kind of ghost class, thus it is not visible in the ancestors chain, but it is there. It is hidden from the output of Foo.ancestors intentionally by the language designer. singleton methods are called by the object(here FOO) directly, on which singleton(per object basis class) class has been created. You can't create an instance of singleton class.

Here is a proof :

Foo.singleton_class.new # can't create instance of singleton class (TypeError)

Do remember also that singleton methods of a class say here Bar, is also available to its descendant class(here Foo). Because meta class of Bar became a superclass of the meta class of Foo, when you write class Foo < Bar...

class Bar
  def self.biz
    puts 11
  end
end

class Foo < Bar
  def self.bar
    puts 12
  end
end

Bar.singleton_class # => #<Class:Bar>
Foo.singleton_class.superclass # => #<Class:Bar>
Arup Rakshit
  • 116,827
  • 30
  • 260
  • 317
  • True that, but, if #bar is an instance method of Foo's singleton class, how can it be called if there is no instance of the singleton class to call on? – BrunoMCBraga Feb 09 '14 at 21:50
  • return, need proof? `Foo.singleton_class.new #=> TypeError: can't create instance of singleton class` – Cary Swoveland Feb 09 '14 at 21:58
  • @CarySwoveland Thanks ... For helping me to this direction, I was also searching a proof against my words. – Arup Rakshit Feb 09 '14 at 22:00
  • I understand i can' do that. I thought the class singleton's hierarchy was like the one presented on the schema below. So, you say that the singleton classes are on the same hierarchy of Foo. I thought that only happened on object singleton classes and not on class singleton classes.Yet i still wonder, if the class methods are instance methods of a singleton class, how are they being called if there is no instance of the singleton class defining that method – BrunoMCBraga Feb 09 '14 at 22:04
  • @returnFromException Just look at this line *singleton methods are called by the object(here FOO) directly, on which singleton(per object basis class) class has been created. You can't create an instance of singleton class.* Also have a look [here](http://rubymonk.com/learning/books/4-ruby-primer-ascent/chapters/39-ruby-s-object-model/lessons/131-singleton-methods-and-metaclasses). – Arup Rakshit Feb 09 '14 at 22:13
  • When you mean directly, you mean, even though you are calling an instance method on a class(which is not possible in other cases)? So i assume the instance methods defined on singleton classes can be called directly on those classes and only from the class they stem from. I even tried: class << Example; self.instanceMethod; end but it told me undefined method – BrunoMCBraga Feb 09 '14 at 22:18
1

To your first question, assuming class X is something containing the following:

class X
  def self.class_method
  end
end

Then class_method is an instance method of X.singleton_class, you can see that by running

X.singleton_class.instance_methods(false)
# ==> [:class_method]

To see how the singleton class is related to the class hierarchy, I found diagrams like this helpful (eigenclass is another name for singleton class):

enter image description here

After that diagram, I thought it was a bit complicated, but using logic, it seems more necessary, assuming the following assumptions hold:

  1. Everything is an object
  2. Every object has a class
  3. Classes can have methods that other classes don't have

From 1, we can deduce that classes are objects, and from 2, we can deduce that classes must then have classes. But to satisfy 3, we need some class between X and Class so that classes can have methods that aren't accessible by other classes. Singleton classes then are a necessary consequence of these three assumptions.

tlehman
  • 5,125
  • 2
  • 33
  • 51