ruby - 从特征类确定类

标签 ruby class metaprogramming eigenclass

在 Ruby 中,获取类 Foo 的特征类很简单

eigenclass = class << Foo; self; end
#=> #<Class:Foo>
eigenclass = Foo.singleton_class #2.1.0
#=> #<Class:Foo>

我对逆运算很感兴趣:从特征类本身获取特征类的所有者:

klass = eigenclass.owner
#=> Foo

我不确定这是否可行,因为特征类是 Class 的匿名子类,所以 Foo 没有出现在它的继承层次结构中。检查特征类的方法列表也不令人鼓舞。 eigenclass.name 返回 nil。唯一让我希望这是可能的:

Class.new # normal anon class
#=> #<Class:0x007fbdc499a050>
Foo.singleton_class
#=> #<Class:Foo>

显然,特征类的 to_s 方法知道关于所有者的一些,即使在实例化特征类时此信息是硬编码的。因此,我知道的唯一方法是一些 hacky Object.const_getting 之类的

Object.const_get eigenclass.to_s[/^#\<Class\:(?<owner>.+)\>$/, :owner]
#=> Foo

最佳答案

使用ObjectSpace.each_object将单例类传递给它以查找与给定单例类匹配的所有类:

Klass = Class.new
ObjectSpace.each_object(Klass.singleton_class).to_a  #=> [Klass]

但是,由于一个类的单例类继承自其父类(super class)的单例类,如果您要查找的类有子类,您将得到多个结果:

A = Class.new
B = Class.new(A)
B.singleton_class.ancestors.include?(A.singleton_class)  #=> true

candidates = ObjectSpace.each_object(A.singleton_class)
candidates.to_a  #=> [A, B]

幸运的是,classes/modules are sortable按它们在继承树中的位置(相同顺序 ancestors 给出)。由于我们知道所有结果都必须是同一继承树的一部分,因此我们可以采用 max获得正确的类(class):

candidates.sort.last  #=> A
ObjectSpace.each_object(B.singleton_class).max  #=> B

关于ruby - 从特征类确定类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21503796/

相关文章:

ruby-on-rails - 在模型中使用 ||= 而不是 = 来定义常量的原因是什么

java - 无法使用带有方法的枚举的动态类参数实例化 EnumMap

c++ - 仅使用 DLL *.h 头文件构建(编译链接)应用程序代码并在运行时加载 DLL 实现(显式链接)

C++模板元编程功夫挑战(替换一个宏函数定义)

ruby-on-rails - 如何更改 Rails 4 has_secure_password 状态消息?

ruby-on-rails - 什么时候在 Rails 应用程序中执行有条件的 before_action 方法?

ruby - 如何处理树顶左递归

actionscript-3 - 如何在 ActionScript 3 中正确测试类继承?

c++ - 有状态的元编程格式不正确吗(还)?

reflection - 反射到底是什么,什么时候是一个好方法?