【问题标题】:Implement Ruby's Object#class method [duplicate]实现 Ruby 的 Object#class 方法
【发布时间】:2013-07-20 13:29:21
【问题描述】:

我正在扩展BasicObject,我想实现Object#class 方法。除了像这样对返回值进行硬编码之外,我不确定如何执行此操作:

class MyObject < BasicObject
  def class
    ::Kernel::eval "::MyObject"
  end
end

MyObject.new.class
#=> MyObject

使用此解决方案,任何从MyObject 继承的类都必须覆盖此方法以保持其准确性。有没有更好的办法?

【问题讨论】:

  • @falsetru:这完全有效!我实际上正在做类似的事情,但我还没有完全做到。谢谢!

标签: ruby


【解决方案1】:

在 Ruby 中无法实现此方法。您需要访问 Ruby 无法访问的三样东西:

  • 类指针
  • 超类指针
  • 虚拟类标志(包括类和单例类都是虚拟类)

Object#class 的工作方式如下:

class Object
  def class
    c = self.__class__
    c = c.__superclass__ while c.__virtual__?
    c
  end
end

还有Class#superclass:

class Class
  def superclass
    c = self.__superclass__
    c = c.__superclass__ while c.__virtual__?
    c
  end
end

而且由于无法获取类指针(请记住:class 方法不会返回它)并且无法获取超类指针(请记住:@987654326 @method 也不返回它)而且你没有办法检查一个类是否是虚拟的,在 Ruby 中不可能编写这个方法。

您需要对运行时内部进行某种特权访问才能做到这一点。

【讨论】:

  • 有趣。感谢分享!
  • @DesAdams: 顺便说一句:当我说“你需要对运行时内部的特权访问”时,当然有可能这些运行时内部实际上作为 Ruby 方法暴露给你,因此您可以可能在 Ruby 中编写 class ......但是您将调用不属于 Ruby 语言规范的特定于解释器的 API,因此您的代码将无法移植。例如,在 Rubinius 中,可能可以按照您的要求进行操作,但它不适用于任何其他实现,因为您将调用特定于 Rubinius 的 API。
  • @Priti:我不明白这与我的答案有什么关系。
【解决方案2】:

由于您拒绝继承Object,因此您几乎缺少所有基本方法,包括classancestors。您需要对所有内容进行硬编码。除了最小的语法,一切都消失了。把它想象成tabla rasa。没有其他方法可以构建您的方法。

Ruby 旨在让所有对象都从 Object 继承,违背这一点不会产生有用的结果。

【讨论】:

    【解决方案3】:

    我被引导到这个可能重复的问题:How do I get the class of a BasicObject instance?

    为该问题提供的解决方案解决了我的问题。谢谢!

    【讨论】:

      猜你喜欢
      • 2015-10-05
      • 1970-01-01
      • 2014-02-22
      • 2018-08-16
      • 1970-01-01
      • 2016-03-28
      • 2021-10-08
      • 2022-01-16
      • 1970-01-01
      相关资源
      最近更新 更多