11
class << self
attr_accessor :n, :totalX, :totalY
end

上記の構文は、クラス インスタンス変数の定義に使用されます。しかし、構文が何を意味するかを考えると、意味が分からないので、このタイプの構文が他のタイプの定義に使用されているかどうか疑問に思っています。ここでの私の混乱のポイントはこれです:

class << self

通常、append 演算子は「右側にあるものを左側にあるオブジェクトに追加する」ことを意味します。しかし、このブロックのコンテキストでは、「このブロックの内容をインスタンスではなくクラス インスタンスの定義に入れる」ことはどのように行われるのでしょうか?

同じ理由で、あるコンテキストクラスで << self がクラスインスタンス変数を定義できるのに、別のコンテキストクラスでは次のようなクラス変数を作成するように見える理由について混乱しています。

class Point
  # Instance methods go here
  class << self
    # Class methods go here
  end
end
4

3 に答える 3

19

Ruby では、既存のクラスを再度開いてメソッドを追加できます。つまり、次のように言えます。

class Foo
  def bob
    return "hello from bob"
  end
end

これらのメソッドは、クラスの内部ディクショナリ (おそらくインスタンス変数) のどこかに格納されますFoo(これはクラスの単なるインスタンスでありClass、したがってインスタンス変数を持ちます)。

しかし驚くべきことは、既存のオブジェクトのインスタンスにメソッドを追加することもできるということです

foo = Foo.new
foo2 = Foo.new

def foo.fred
  return "I am fred"
end


foo.fred  #=> "I am fred"
foo2.fred #=> NoMethodError

しかし、このメソッドは実際にどこに保存されていますか?

Ruby は舞台裏で新しいクラス ( singleton classmetaclass、またはeigenclassと呼ばれることもあります) を作成し、 -classとそのインスタンスのの継承階層に挿入されます。Foo

したがって、継承関係は次のようになります。

foo < (eigenclass of foo) < Foo < Class

(foo.superclass と言うと、シングルトン クラスは表示されません)

-syntax は、この特別なクラスを取得する方法であり、class << X直接操作できます。次のコード ブロックはまったく同じです。

def foo.bar
  return "xy"
end

# is exactly the same as

class << foo
  def bar
    return "xy"
  end
end

したがって、 と の類似性は偶然class Foo < Barclass << Fooはなく、両方で継承が行われています。

class << X「X のメタクラスを開く」と考えてください。

Ruby で覚えておくべきことは、クラス自体は単なるオブジェクトだということです。(クラスのインスタンスClass)だから、あなたが言うなら:

class Foo
  class << self
    def k
      return "x"
    end
  end
end

(このコード ブロックでselfは にバインドされています) も の固有クラスのインスタンス メソッドであり、これにより のクラス メソッドになります。FookFooFoo

これはすべて、つるはしのクラスに関する章でより明確に説明されています (残念ながら、Web バージョンには図が含まれていません)。

于 2009-05-22T10:19:05.840 に答える
2

このクラスは、すべてのアクセサーとインスタンス変数を含むメンバーのディクショナリを含むものと考えてください。クラスに「自分自身」に「追加」するように指示すると、「これらをクラスメンバーの辞書に追加する」ということになります。

ただし、表記は少しひねくれています。

于 2009-05-22T05:35:02.927 に答える
1

「追加」演算子の観点から考えると、実際には混乱します。class Fooより良い見方は、クラス Foo を開くのと同じように、つまり、'self' をクラス オブジェクト Foo に設定し、必要に応じてそれを作成してclass << self、現在の 'self' オブジェクトの固有クラスを開くことです。self に限定されないことに注意してください。任意のオブジェクト bar に対して、class << bar と言って、そのオブジェクトの固有クラスを開くことができます。

class A
  def hello
    print "hello world"
  end
end

a = A.new
b = A.new

class << a
  def goodbye
    print "goodbye cruel world"
  end
end

a.hello
b.hello
a.goodbye
b.goodbye
于 2009-05-22T06:33:44.650 に答える