Quelqu'un peut-il me parler de la différence entre les variables de classe et les variables d'instance de classe?
91
Quelqu'un peut-il me parler de la différence entre les variables de classe et les variables d'instance de classe?
Une variable de classe ( @@
) est partagée entre la classe et tous ses descendants. Une variable d'instance de classe ( @
) n'est pas partagée par les descendants de la classe.
Variable de classe ( @@
)
Prenons une classe Foo avec une variable de classe @@i
et des accesseurs pour la lecture et l'écriture @@i
:
class Foo
@@i = 1
def self.i
@@i
end
def self.i=(value)
@@i = value
end
end
Et une classe dérivée:
class Bar < Foo
end
On voit que Foo et Bar ont la même valeur pour @@i
:
p Foo.i # => 1
p Bar.i # => 1
Et changer @@i
dans un le change dans les deux:
Bar.i = 2
p Foo.i # => 2
p Bar.i # => 2
Variable d'instance de classe ( @
)
Créons une classe simple avec une variable d'instance de classe @i
et des accesseurs pour la lecture et l'écriture @i
:
class Foo
@i = 1
def self.i
@i
end
def self.i=(value)
@i = value
end
end
Et une classe dérivée:
class Bar < Foo
end
On voit que bien que Bar hérite des accesseurs pour @i
, il n'hérite pas de @i
lui-même:
p Foo.i # => 1
p Bar.i # => nil
Nous pouvons définir Bar's @i
sans affecter les Foo @i
:
Bar.i = 2
p Foo.i # => 1
p Bar.i # => 2
Vous devez d'abord comprendre que les classes sont aussi des instances - des instances de la
Class
classe.Une fois que vous comprenez cela, vous pouvez comprendre qu'une classe peut être associée à des variables d'instance comme un objet normal (lu: non-classe).
Notez qu'une variable d'instance sur
Hello
est complètement indépendante et distincte d'une variable d'instance sur une instance deHello
Une variable de classe, en revanche, est une sorte de combinaison des deux ci-dessus, car elle est accessible sur
Hello
elle-même et ses instances, ainsi que sur les sous-classes deHello
et leurs instances:Beaucoup de gens disent qu'il faut éviter en
class variables
raison du comportement étrange ci-dessus et recommandent d'utiliser à laclass instance variables
place.la source
Je souhaite également ajouter que vous pouvez accéder à la variable de classe (
@@
) à partir de n'importe quelle instance de la classeMais vous ne pouvez pas faire de même pour la variable d'instance de classe (
@
)la source
Foo.i
, mais comment pouvez-vous faire la même chose pour chaque instance de cette classeFoo.new.i
?#class
.#class
Personnellement, je pense que les usages quand on les appelle, mais ceself
sont des odeurs de code. Vous pouvez même aller plus loin et implémenter des accesseurs d'instancei
eti=
ce délégué à leurs#class
équivalents, auquel cas vous pouvez le faireFoo.new.i
. Je ne recommande pas de le faire car cela crée une interface déroutante, suggérant que vous modifiez un membre d'objet.