Isto é uma tradução de um artigo de Martin Fowler sobre ClassInstanceVariable (uma variável de instância de classe).
Quando se aprende algo sobre objectos normalmente aprendemos que esses objectos capturam dois tipos de dados: instância (exemplar) e classe. As variáveis de instância são as mais comuns, os dados variam de instância para instância do objecto. As variáveis de classe, também conhecidas por variávies estáticas, são partilhadas por todas as instâncias (exemplares) da classe. Cada instância aponta para o mesmo valor e qualquer alteração é vista por todas as instâncias. As variáveis de classe são muito menos comuns do que as variáveis de instância especialmente variáveis de classe que sejam mutáveis.
Um dos aspectos complexos das variáveis de classe é como é que elas interagem com uma hierárquia de herança. Consideremos uma variável de classe que é usada para guardar a própria instância.
class Empregado@@exemplares = []def self.exemplaresreturn @@exemplaresenddef guardar@@exemplares << selfenddef initialize nome@nome = nomeendendEmpregado.new("Martins").guardarEmpregado.new("Roberta").guardarEmpregado.new("Eurico").guardarputs Empregado.exemplares.size
Não há aqui nenhuma surpresa, há três empregados. Agora experimentemos isto:
class Empregado@@exemplares = []def self.exemplares@@exemplaresenddef guardar@@exemplares << selfenddef initialize nome@nome = nomeendendclass Programador < Empregado; endclass Restodopessoal < Empregado; endRestodopessoal.new('Martins').guardarRestodopessoal.new('Roberta').guardarProgramador.new('Eurico').guardarputs Restodopessoal.exemplares.sizeputs Programador.exemplares.size
O resultado é 3 e 3, enquanto preferiamos obter 2 e 1. A razão por que isto se passa é que a variável de classe é partilhada ao longo de todas as instâncias da classe e essas incluem todas as subclasses. Há duas classes mas só uma variável.
Por vezes esta variável que perpassa a totalidade da hieráquia é o que necessitamos, mas por vezes, como neste caso, preferiamos ter uma variável diferente em cada classe. Podemo-nos referir a uma variável de instância de classe do mesmo modo que a uma variável de classe, mas teremos um valor diferente por classe.
O suporte para variáveis de instâncias de classe não é comum nas linguagens OO, mas não é difícil de criarmos um nós próprios. O modo óbvio de o criar seria o de usar um dicionários de chaves por nome de classe.
class Empregado@@exemplares = {}def self.exemplares@@exemplares[self]enddef guardar@@exemplares[self.class] || = []@@exemplares[self.class] || = << selfenddef initialize nome@nome = nomeendendclass Programador < Empregado; endclass Restodopessoal < Empregado; endRestodopessoal.new('Martins').guardarRestodopessoal.new('Roberta').guardarProgramador.new('Eurico').guardarputs Restodopessoal.exemplares.sizeputs Programador.exemplares.size
Pode usar esta técnica em qualquer linguagem OO. Ruby contudo tem de facto variáveis de instância de classe.
class Empregadoclass << self; attr_accessor :exemplares; enddef guardarself.class.exemplares || = []self.class.exemplares << selfenddef initialize nome@nome = nomeendendclass Programador < Empregado; endclass Restodopessoal < Empregado; endRestodopessoal.new('Martins').guardarRestodopessoal.new('Roberta').guardarProgramador.new('Eurico').guardarputs Restodopessoal.exemplares.sizeputs Programador.exemplares.size
A definição da variável de instância de classe é o fragmento class << self; attr_accessor :exemplares; end.
2 comentários:
A simbiose entre o Ruby e o Rails é tão intensa que muitos pensam que Ruby on Rails é uma linguagem e por isso é muito difícil encontrar material de qualidade sobre Ruby(sem Rails). Boa a sua contribuição.
Há muito tempo que não passeio por linguagens de programação, parece ter chegado o momento para voltar a falar das mesmas.
Enviar um comentário