質問

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.

役に立ちましたか?

解決

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>

他のヒント

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.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top