获取没有类方法的Ruby类名

时间:2012-04-03 00:26:21

标签: ruby oop class object ruby-1.9.3

如何在Ruby中获取BasicObject实例的类名?例如,说我有这个:

class MyObjectSystem < BasicObject
end
puts MyObjectSystem.new.class

如何使此代码成功?

编辑:我发现Object的实例方法class被定义为return rb_class_real(CLASS_OF(obj));。有没有办法从Ruby使用它?

3 个答案:

答案 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)然后返回selfself现在已成为单例类),然后可以将其分配给变量以执行您想要的操作。

如果您想要更好地解释所有这些,我建议您阅读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