为什么单例类是其自身的实例?

时间:2019-10-01 17:30:35

标签: ruby

这个问题很难说出来。所有对象都有一个singleton类(又名ghost类),在该类上我们可以为该对象定义方法。

但是当我们检查单例类时,我们看到它是一个类的实例,它们都是同一个对象。

o = Object.new
o.singleton_class.instance_eval { self.object_id } # => 47082984969880
o.singleton_class.class_eval { self.object_id } # => 47082984969880

这是因为单例类是匿名类。

o.singleton_class # => #<Class:#<Object:0x0000557ed623d8b8>>
o.singleton_class.name # => nil

匿名类是Class类型的类

o.singleton_class.class # => Class

Class的类为Class

Class.class # => Class
Class.new.class == Class # => true

Class是它本身的一个实例。

因此,我们可以看到singleton类是类型为Class的匿名类,它们是Class的相同实例

Class.object_id # => 47001622014720
o.singleton_class.class.object_id # => 47001622014720

但是为什么要使用class_evalinstance_eval却得到相同的对象,而在没有eval的情况下查看实例和类却没有呢?

o.singleton_class.instance_eval { self.object_id } # => 47082984969880
o.singleton_class.class_eval { self.object_id }    # => 47082984969880
o.singleton_class.object_id                        # => 47082984969880
o.singleton_class.class.object_id                  # => 47001622014720

1 个答案:

答案 0 :(得分:0)

从o.singleton_class.class.object_id获得47001622014720的地方实际上与Class.object_id相同,后者也应产生47001622014720。

更进一步,尝试使用祖先而不是object_id来查看您是否可以对发生的事情有更多的了解。

o.singleton_class.instance_eval { self.ancestors } # => [#<Class:#<Object:0x00007f9b3c0465d0>>, Object, Kernel, BasicObject]
o.singleton_class.class_eval { self.ancestors }    # => [#<Class:#<Object:0x00007f9b3c0465d0>>, Object, Kernel, BasicObject]
o.singleton_class.ancestors # => [#<Class:#<Object:0x00007f9b3c0465d0>>, Object, Kernel, BasicObject]
o.singleton_class.class.ancestors # => [Class, Module, Object, Kernel, BasicObject]