Ruby sont là toutes les applications connexes de la syntaxe: classe << auto ... fin
Question
class << self
attr_accessor :n, :totalX, :totalY
end
La syntaxe est utilisée ci-dessus pour la définition des variables d'instance de classe. Mais quand je pense à ce que la syntaxe implique, il ne fait pas de sens pour moi, alors je me demande si ce type de syntaxe est utilisée pour tous les autres types de définitions. Mon point de confusion ici est la suivante:
class << self
L'opérateur append signifie normalement « ajouter ce qui est sur le droit à l'objet à gauche ». Mais dans le contexte de ce bloc, comment cela ajouter jusqu'à « mettre le contenu de ce bloc dans la définition de l'instance de la classe plutôt que l'instance »?
Pour la même raison, je suis confus quant à la raison pour laquelle dans une classe de contexte << auto peut définir des variables d'instance de classe alors que dans une autre, il semble créer des variables de classe comme ici:
class Point
# Instance methods go here
class << self
# Class methods go here
end
end
La solution
Ruby vous pouvez rouvrir les classes et ajouter des méthodes existantes. Autrement dit, vous pouvez dire:
class Foo
def bob
return "hello from bob"
end
end
ces méthodes sont stockés quelque part dans un dictionnaire interne (peut-être une variable d'instance) de la Foo
classe (qui est juste une instance de la Class
classe et donc a variables d'instance)
Mais la chose est surprenante, que vous pouvez également ajouter des méthodes instances d'objets existants
foo = Foo.new
foo2 = Foo.new
def foo.fred
return "I am fred"
end
foo.fred #=> "I am fred"
foo2.fred #=> NoMethodError
Où est cette méthode réellement stocké ?
Turns out Ruby crée une nouvelle classe dans les coulisses (parfois appelé class singleton , métaclasse ou eigenclass ) qui est insérée dans l'héritage heirarchy entre la Foo
classe et son instance.
Ainsi, la relation d'héritage ressemble à ça:
foo < (eigenclass of foo) < Foo < Class
(si vous dites foo.superclass vous ne verrez pas la classe singleton)
la class << X
-syntaxe est un moyen d'arriver à cette classe spéciale, afin que vous puissiez le manipuler directement. Les blocs de code suivants sont exactement équivalentes:
def foo.bar
return "xy"
end
# is exactly the same as
class << foo
def bar
return "xy"
end
end
Ainsi, la similitude entre class Foo < Bar
et class << Foo
est pas par hasard, il y a l'héritage se passe dans les deux.
Pensez à class << X
comme "ouvrir la métaclasse de X"
La chose à retenir est que Ruby dans les classes elles-mêmes ne sont que des objets. (Les instances de la Class
de classe), donc si vous dites:
class Foo
class << self
def k
return "x"
end
end
end
(self
est lié à Foo
dans ce bloc de code) de manière k
est une méthode instance des eigenclass de Foo
, ce qui en fait une méthode de classe pour Foo
tout cela est plus clairement expliqué dans le (la version web ne contient pas les diagrammes, malheureusement) et _whys en voyant métaclasses Il est clair que
Autres conseils
Pensez à la classe comme contenant un dictionnaire des membres, y compris tous les accesseurs et les variables d'instance. Lorsque vous dites la classe à « ajouter » à « lui-même », vous dites « ajoutez-les au dictionnaire des membres de la classe. »
Je vais accorder la notation est un peu louche, cependant.
il est en fait déroutant de penser en termes d'un opérateur « ajouter ». une meilleure façon de regarder est que, tout comme class Foo
ouvre la classe Foo, qui est, il définit « soi » à l'objet de classe Foo, créant si nécessaire, si class << self
ouvre les eigenclass du courant objet « auto ». noter qu'il ne se limite pas à l'auto -. pour une barre d'objets, vous pouvez dire la classe << bar pour ouvrir les eigenclass de cet objet
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