从单个类中检索Ruby对象?

jslywgbw  于 2023-05-28  发布在  Ruby
关注(0)|答案(4)|浏览(117)

从Ruby对象访问singleton class是可以的:

some_object.singleton_class

是否可以进行反向操作:在singleton类中访问原始对象?

class << some_object
  # how to reference some_object without actually typing some_object?
end

我想把这个method弄干:

class Example
  PARENTS = []
  class << PARENTS
    FATHER = :father
    MOTHER = :mother
    PARENTS.push(FATHER, MOTHER)
  end
end

并试图用更通用的东西替换类中的PARENTS

n3ipq98p

n3ipq98p1#

我不知道任何内置的方法或关键字,但你可以写一个方法,将一个(单例)方法添加到对象的单例类中,返回对象本身:

class Object
  def define_instance_accessor(method_name = :instance)
    singleton_class.define_singleton_method(method_name, &method(:itself))
  end
end

用途:

obj = Object.new              #=> #<Object:0x00007ff58e8742f0>
obj.define_instance_accessor
obj.singleton_class.instance  #=> #<Object:0x00007ff58e8742f0>

在您的代码中:

class Example
  PARENTS = []
  PARENTS.define_instance_accessor
  class << PARENTS
    FATHER = :father
    MOTHER = :mother
    instance.push(FATHER, MOTHER)
  end
end

在内部,YARV将对象存储在名为__attached__的示例变量中。示例变量没有通常的@前缀,因此在Ruby中不可见或不可访问。
这里有一个小的C扩展来暴露它:

#include <ruby.h>

static VALUE
instance_accessor(VALUE klass)
{
    return rb_ivar_get(klass, rb_intern("__attached__"));
}

void Init_instance_accessor()
{
    rb_define_method(rb_cClass, "instance", instance_accessor, 0);
}

用途:

irb -r ./instance_accessor
> obj = Object.new
#=> #<Object:0x00007f94a11e1260>
> obj.singleton_class.instance
#=> #<Object:0x00007f94a11e1260>
>
yvt65v4c

yvt65v4c2#

只是出于好奇(请不要在家里或学校使用)

object = []
class << object
  type, id = to_s[/(?<=:#<).*?(?=>)/].split(':')
  ObjectSpace.each_object(Kernel.const_get(type)).find do |e|
    e.__id__ == id.to_i(16) >> 1
  end << :father
end   
#⇒ [:father]
pzfprimi

pzfprimi3#

我们可以这样做。

def singleton_class_to_object(sc)
  ObjectSpace.each_object(Object).find { |o|
    (o.singleton_class == sc) rescue false }
end

o = Object.new
  #=> #<Object:0x00005b52e502d030> 
singleton_class_to_object(o.singleton_class)
  #=> #<Object:0x00005b52e502d030> 

class C; end
singleton_class_to_object(C.singleton_class)
  #=> C

内嵌的拯救是处理直接对象o,它没有单例类。
在MRI v2.7.0中,

ObjectSpace.each_object(Object).to_a.size
  #=> 35362

微薄的收入

ma8fv8wu

ma8fv8wu4#

Class#attached_object(Ruby 3.2+)

Ruby 3.2开始,有一个Class#attached_object方法:
返回接收者为单例类的对象。
如果类不是单例类,则引发TypeError
例如:

class Foo; end

Foo.singleton_class.attached_object     #=> Foo
Foo.attached_object                     #=> TypeError: `Foo' is not a singleton class
Foo.new.singleton_class.attached_object #=> #<Foo:0x000000010491a370>
TrueClass.attached_object               #=> TypeError: `TrueClass' is not a singleton class
NilClass.attached_object                #=> TypeError: `NilClass' is not a singleton class

来源:

相关问题