Alguém pode me dizer sobre a diferença entre variáveis de classe e variáveis de instância de classe?
91
Alguém pode me dizer sobre a diferença entre variáveis de classe e variáveis de instância de classe?
Uma variável de classe ( @@
) é compartilhada entre a classe e todos os seus descendentes. Uma variável de instância de classe ( @
) não é compartilhada pelos descendentes da classe.
Variável de classe ( @@
)
Vamos ter uma classe Foo com uma variável de classe @@i
e acessadores para leitura e escrita @@i
:
class Foo
@@i = 1
def self.i
@@i
end
def self.i=(value)
@@i = value
end
end
E uma classe derivada:
class Bar < Foo
end
Vemos que Foo e Bar têm o mesmo valor para @@i
:
p Foo.i # => 1
p Bar.i # => 1
E mudar @@i
em um muda em ambos:
Bar.i = 2
p Foo.i # => 2
p Bar.i # => 2
Variável de instância de classe ( @
)
Vamos fazer uma classe simples com uma variável de instância de classe @i
e acessadores para leitura e escrita @i
:
class Foo
@i = 1
def self.i
@i
end
def self.i=(value)
@i = value
end
end
E uma classe derivada:
class Bar < Foo
end
Vemos que, embora Bar herde os acessadores de @i
, ele não herda a @i
si mesmo:
p Foo.i # => 1
p Bar.i # => nil
Podemos definir Bar @i
sem afetar Foo @i
:
Bar.i = 2
p Foo.i # => 1
p Bar.i # => 2
Primeiro você deve entender que as classes também são instâncias - instâncias da
Class
classe.Depois de entender isso, você pode entender que uma classe pode ter variáveis de instância associadas a ela, assim como um objeto normal (leia-se: não classe) pode.
Observe que uma variável de instância em
Hello
é completamente não relacionada e distinta de uma variável de instância em uma instância deHello
Uma variável de classe, por outro lado, é uma espécie de combinação das duas anteriores, pois é acessível a
Hello
si mesma e às suas instâncias, bem como às subclasses deHello
e suas instâncias:Muitas pessoas dizem para evitar
class variables
por causa do comportamento estranho acima e recomendam o uso declass instance variables
.fonte
Também quero acrescentar que você pode obter acesso à variável de classe (
@@
) a partir de qualquer instância da classeMas você não pode fazer o mesmo para a variável de instância de classe (
@
)fonte
Foo.i
, mas como você pode fazer o mesmo para todas as instâncias dessa classeFoo.new.i
?#class
. Eu pessoalmente acho que os#class
usos quando chamados em qualquer coisa, masself
são cheiros de código embora. Você pode até mesmo dar um passo adiante e implementar acessadores de instânciai
ei=
delegar para seus#class
equivalentes, caso em que você pode fazerFoo.new.i
. Não recomendo fazer isso, pois cria uma interface confusa, sugerindo que você está modificando um membro do objeto.