5

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

class MyObjectSystem < BasicObject
end
puts MyObjectSystem.new.class

我怎样才能使这段代码成功?

编辑:我发现 Object 的实例方法class被定义为return rb_class_real(CLASS_OF(obj));. 有什么方法可以从 Ruby 中使用它?

4

3 回答 3

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您可以调用的方法。

编辑

评论中要求的进一步解释:

假设您有一个 objectobj是 class 的实例Foo。除了在 的父类中定义的方法之外,还obj从定义在 class 中的方法获取其实例方法,依此类推。Ruby 允许您直接在对象上定义方法,这些方法只能由该特定对象访问,如下所示FooFoo

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 对象模型。

于 2012-04-03T02:30:44.227 回答
1

我必须在几分钟后离开,所以我不能自己测试它,但看起来你可以制作一个单独的模块,使用ffirb_class_real从 libruby调用。如果我有更多的时间,我会先测试它,但还没有人回答,我不想让你完全冷落。

于 2012-04-03T01:04:44.140 回答
0

根据 Jeff Smith 的回答,您无需修改​​即可执行此操作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
于 2016-05-04T15:13:52.017 回答