在 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/