2011-08-13 5 views
6

これは、あなたがメタクラスやシングルトンクラスは、デフォルトto_s出力に接続されているオブジェクトの表現を見ることができます質問「Given an instance of a Ruby object, how do I get its metaclass?Rubyメタクラスが与えられていると、それがどのインスタンスに付属しているのですか?

の逆です:

s = "hello" 
s_meta = class << s; self; end 
s_meta.to_s # => "#<Class:#<String:0x15004dd>>" 

class C; end 
c_meta = class << C; self; end 
c_meta.to_s # => "#<Class:C>" 

は、することが可能ですこのオブジェクトを返すメソッドClass.attachedを実装します(レシーバが通常のクラスの場合はnil)。

s_meta.attached # => s 
c_meta.attached # => C 
C.attached # => nil 

答えて

8

ObjectSpaceを使用した醜い(まだ動作している)ハックがあります。同様に、演奏や多分デバッグを除いて決して使うべきではないもの。あなたはちょうどそう、その最初の(そして唯一の)インスタンスをしたい:

ObjectSpace.each_object(self).first 

が、それはシングルトンクラスだかどうかを決定するために、それはシングルトンクラスです(またはeigenclass場合はancestorsは、その受信機は含まれません奇妙なプロパティを使用することができ、

ObjectSpace.each_object(self).first unless ancestors.include? self 

edgecasesを気にする人は、そのクラスがシングルトンクラスでもある3つのオブジェクトがあります。

[true, false, nil].each do |o| 
    o.class.send(:define_method, :attached) { o } 
end 
3

私はMRIについて知らない。 JRubyので

、次はあなたが望むものを返します。

require 'java' 
class A 
    def self.meta 
    class << self; self; end 
    end 
end 

A.meta.to_java.attached 
1

あなたは添付オブジェクトを格納するためにmetaclassを定義することができます。

class Class 
    attr_accessor :attached 
end 

class Object 
    def metaclass 
    meta = class << self; self; end 
    meta.attached = self 
    meta 
    end 
end 

class A; end 

a = A.new 
a_meta = a.metaclass 
p a      #=> #<A:0xb74ed768> 
p a_meta    #=> #<Class:#<A:0xb74ed768>> 

obj = a_meta.attached 
p obj     #=> #<A:0xb74ed768> 

puts obj == a   #=> true 
p A.attached   #=> nil 
1

あなたは(MRIの実装で)inspectからそれを得ることができます:オブジェクトIDとinspectとの関係については

class Class 
    def attached 
    # first, match the object reference from inspect 
    o_ref = inspect.match /0x([0-9a-f]+)>>$/ 

    # if not found, it's not a metaclass 
    return nil unless o_ref 

    # calculate the object id from the object reference  
    o_id = (o_ref[1].to_i(16) >> 1) - 0x80000000 

    # get the object from its id 
    ObjectSpace._id2ref o_id 
    end 
end 

# testing... 
class A; end 

a = A.new 
a_meta = class << a; self; end 

p a      #=> #<A:0xb7507b00> 
p a_meta     #=> #<Class:#<A:0xb7507b00>> 
p a_meta.attached   #=> #<A:0xb7507b00> 
p a == a_meta.attached  #=> true 
p A.attached    #=> nil 

を、this answerを参照してください。

関連する問題