这是问题“
Given an instance of a Ruby object,how do I get its metaclass?”的反转
您可以在默认的to_s输出中看到元类或单例类附加到的对象的表示:
s = "hello" s_Meta = class << s; self; end s_Meta.to_s # => "#<Class:#<String:0x15004dd>>" class C; end c_Meta = class << C; self; end c_Meta.to_s # => "#<Class:C>"
是否可以实现返回此对象的方法Class.attached(如果接收者是常规类,则为nil)?
s_Meta.attached # => s c_Meta.attached # => C C.attached # => nil
解决方法
使用ObjectSpace有一个丑陋(但仍在工作)的黑客攻击.比如,除了玩游戏和调试之外你不应该使用的东西.你只想要它的第一个(也是唯一的)实例,所以:
ObjectSpace.each_object(self).first
要确定它是否是单例类,您可以使用奇怪的属性,如果它是单例类(或本征类或魔法类),祖先将不包括其接收器:
ObjectSpace.each_object(self).first unless ancestors.include? self
如果你关心edgecases,有三个对象,它们的类也是它们的单例类.
[true,false,nil].each do |o| o.class.send(:define_method,:attached) { o } end