class << self
est plus qu'un moyen de déclarer des méthodes de classe (bien qu'il puisse être utilisé de cette façon). Probablement que vous avez vu une utilisation comme:
class Foo
class << self
def a
print "I could also have been defined as def Foo.a."
end
end
end
Cela fonctionne, et équivaut à def Foo.a
, mais la façon dont cela fonctionne est un peu subtile. Le secret est que self
, dans ce contexte, fait référence à l'objet Foo
, dont la classe est une sous-classe anonyme unique de Class
. Cette sous-classe est appelée Foo
classe propre. Donc def a
crée une nouvelle méthode appelée a
dans la classe propre Foo
, accessible par la syntaxe d'appel de méthode normale: Foo.a
.
Maintenant, regardons un autre exemple:
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
Cet exemple est le même que le dernier, mais il peut être difficile de dire au début. frob
est défini, pas sur la classe String
, mais sur la classe propre de str
, une sous-classe anonyme unique de String
. Donc str
a une méthode frob
, mais les instances de String
en général ne le font pas. Nous pourrions aussi avoir des méthodes surchargées de String (très utile dans certains scénarios de test difficiles).
Maintenant nous sommes équipés pour comprendre votre exemple original. À l'intérieur Foo
méthode d'initialisation, self
se réfère pas à la classe Foo
, mais à certains en particulier de Foo
. Sa classe propre est une sous-classe de Foo
, mais elle n'est pas Foo
; ça ne pouvait pas l'être, sinon le truc que nous avons vu dans le second exemple ne pouvait pas fonctionner. Donc, pour continuer votre exemple:
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.
Espérons que cela aide.
Ainsi donc, chaque instance est une sous-classe anonyme de la classe créée? –
* class * de chaque instance est une sous-classe anonyme de la classe créée. La classe f1 est une sous-classe anonyme de Foo, la classe de Foo est une sous-classe anonyme de Class. –
belle réponse :) beaucoup de gens ne comprennent pas cela aussi clairement que vous le faites. – horseyguy