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
ます。したがって、の固有クラスで呼び出される新しいメソッドを作成し、通常のメソッド呼び出し構文でアクセスできます: .def a
a
Foo
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
の初期化メソッド内でself
は、 クラスFoo
ではなく、 の特定のインスタンスを参照しFoo
ます。その固有クラスは のサブクラスですFoo
が、そうではありませんFoo
。そうでないと、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.
お役に立てれば。