移除Object常量后为何仍可通过相关方法访问该常量?
为什么移除
Object常量后仍能通过String.superclass获取到它? 先跟大家复现一下问题里的操作流程:
操作步骤
- 检查
Object常量是否存在:Module.const_defined?('Object') #=> true - 移除
Object常量:Object.send(:remove_const, 'Object') #=> Object - 确认常量已被移除:
Module.const_defined?('Object') #=> false
这时候问题来了:
既然
Object常量已经被移除了,为啥下面这段代码还能正常返回Object相关结果?String.superclass #=> Object new_object = String.superclass.new #=> #<Object:0x00007fdc18382858> new_object.class #=> Object
核心原因:常量绑定≠对象本身
其实这是Ruby里一个很关键的概念:常量只是对象的一个"名字绑定",移除常量只是删掉这个名字和对象的关联,并不会销毁对象本身。
具体来说:
- 当你调用
remove_const时,只是把Module命名空间里的Object这个名字,和对应的Object类对象之间的绑定关系解除了。但Object这个类对象并没有消失——因为String的superclass属性一直直接引用着它,只要有活跃的引用,Ruby的垃圾回收就不会把这个对象删掉。 String.superclass返回的是实际的Object类对象,根本不需要通过常量名去查找。哪怕常量名字没了,这个对象依然存在,你照样能调用它的new方法创建实例。- 至于
new_object.class返回的Object,其实是这个类对象的to_s输出结果——这是对象自身携带的标识名称,和之前的常量名称是两码事,哪怕常量被删了,对象自己还记得"我叫Object"。
打个比方:常量就像你给朋友起的外号,你把外号忘了,但朋友本身还在,你的通讯录里依然存着他的联系方式,你照样能找到他,他也知道自己叫啥~
内容的提问来源于stack exchange,提问作者Andrey Deineko
相关产品推荐
相关产品推荐

