1. ホーム
  2. ruby

[解決済み] eigenclassはself.classと同じように見えるのに、なぜ違うのですか?

2023-06-02 10:09:22

疑問点

どこかでメモを取り損ねたので、説明してほしいのですが。

なぜオブジェクトの固有クラスは self.class ?

class Foo
  def initialize(symbol)
    eigenclass = class << self
      self
    end
    eigenclass.class_eval do
      attr_accessor symbol
    end
  end
end

私の論理では、固有クラスと class.self を同一視する私の論理は、むしろ単純なものです。

class << self は、インスタンスメソッドではなく、クラスメソッドを宣言する方法です。これは def Foo.bar .

というわけで、クラスオブジェクトへの参照内で self と同じになるはずです。 self.class . これは class << selfselfFoo.class に変更し、クラスメソッド/属性の定義に使用します。

私が混乱しているだけなのでしょうか?それとも、これはRubyのメタプログラミングの巧妙なトリックなのでしょうか?

どのように解決するのですか?

class << self は、単にクラスメソッドを宣言する方法以上のものです(そのように使うこともできますが)。 おそらく、次のような使い方を見たことがあるのではないでしょうか。

class Foo
  class << self
    def a
      print "I could also have been defined as def Foo.a."
    end
  end
end

これは、次のように動作します。 def Foo.a と同じですが、その動作は少し微妙です。 その秘密は self は、この文脈では、オブジェクト Foo の一意の匿名サブクラスであるオブジェクトを指します。 Class . このサブクラスは Foo 's 固有クラス . そこで def a という新しいメソッドを作成します。 aFoo の固有クラスで、通常のメソッド呼び出し構文でアクセスできます。 Foo.a .

では、別の例を見てみましょう。

str = "abc"
other_str = "def"

class << str
  def frob
    return self + "d"
  end
end

print str.frob # => "abcd"
print other_str.frob # => raises an exception, 'frob' is not defined on other_str

この例は、最初はわかりにくいかもしれませんが、前回と同じです。 frob が定義されていますが、その上ではなく String の固有値で定義されます。 str の一意の匿名サブクラスである String . ですから str には frob メソッドがありますが、インスタンス String のインスタンスは一般にそうではありません。 また、Stringのメソッドをオーバーライドすることもできます (特定のトリッキーなテストシナリオで非常に便利です)。

これで、元の例を理解することができるようになりました。 内部 Foo の initialize メソッドの中です。 self はクラスではなく Foo というクラスではなく、ある特定の インスタンス Foo . その固有クラスは Foo のサブクラスですが、それは Foo でなければ、2番目の例で見たようなトリックが働くはずがありません。 そうでなければ、2番目の例で見たトリックはうまくいきません。

f1 = Foo.new(:weasels)
f2 = Foo.new(:monkeys)

f1.weasels = 4 # Fine
f2.monkeys = 5 # Also ok
print(f1.monkeys) # Doesn't work, f1 doesn't have a 'monkeys' method.

これが役立つといいのですが。