如何在Ruby中获取BasicObject实例的类名?例如,说我有这个:
class MyObjectSystem < BasicObject
end
puts MyObjectSystem.new.class
如何使此代码成功?
编辑:我发现Object的实例方法class
被定义为return rb_class_real(CLASS_OF(obj));
。有没有办法从Ruby使用它?
答案 0 :(得分:8)
我花了一些时间和irb一起玩,并想出了这个:
class BasicObject
def class
klass = class << self; self; end # get the object's singleton class
klass.superclass # the superclass of an object's singleton class is that object's class
end
end
这将为从BasicObject继承的任何对象提供一个可以调用的#class
方法。
修改
评论中要求的进一步解释:
假设你有对象obj
,它是类Foo
的一个实例。 obj
除了在Foo
的父类中定义的方法之外,还从类Foo
中定义的方法获取其实例方法,依此类推依赖继承链。 Ruby允许您直接在对象上定义方法,这些对象只能访问该特定对象,如
obj = Foo.new
def obj.hello
puts "hello"
end
obj.hello #=> hello
other_obj = Foo.new
other_obj.hello #=> Method missing error
你可以这样做的原因是因为每个对象都有一个叫做单例类的东西(或者有时称为本征类),你实际上是在定义方法。这个单例类实际上存在于对象的实际类正下方的对象的继承链中。这使对象的实际类,在此示例中为Foo
,是对象的单例类的超类。
您在答案中看到的class << self
行是用于输入对象的单例类范围的特殊语法。因此,在上面的示例中,您还可以在对象的单例类中定义一个方法,如此
class << obj
def goodbye
puts "goodbye"
end
end
obj.goodbye #=> goodbye
所以行class << self; self; end
正在打开对象的单例类(无论对象当前是self
)然后返回self
(self
现在已成为单例类),然后可以将其分配给变量以执行您想要的操作。
如果您想要更好地解释所有这些,我建议您阅读Metaprogramming Ruby。它绝对可以让您更好地理解整个Ruby对象模型。
答案 1 :(得分:1)
我必须在几分钟内离开,因此我无法自己测试,但似乎您可以创建一个单独的模块,使用ffi从libruby调用rb_class_real
。如果我有更多的时间,我会先测试它,但没有其他人已经回答,我不希望你完全离开你。
答案 2 :(得分:0)
基于Jeff Smith的answer,您可以在不修改BasicObject
的情况下执行此操作:
class << object; self; end.superclass
其中object
是您想要的类的对象的实例,即
irb(main):001:0> object = BasicObject.new
(Object doesn't support #inspect)
=>
irb(main):002:0> class << object; self; end.superclass
=> BasicObject