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.exemplares
return @@exemplares
end
def guardar
@@exemplares << self
end
def initialize nome
@nome = nome
end
end
Empregado.new("Martins").guardar
Empregado.new("Roberta").guardar
Empregado.new("Eurico").guardar
puts Empregado.exemplares.size
Não há aqui nenhuma surpresa, há três empregados. Agora experimentemos isto:
class Empregado
@@exemplares = []
def self.exemplares
@@exemplares
end
def guardar
@@exemplares << self
end
def initialize nome
@nome = nome
end
end
class Programador < Empregado; end
class Restodopessoal < Empregado; end
Restodopessoal.new('Martins').guardar
Restodopessoal.new('Roberta').guardar
Programador.new('Eurico').guardar
puts Restodopessoal.exemplares.size
puts 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]
end
def guardar
@@exemplares[self.class] || = []
@@exemplares[self.class] || = << self
end
def initialize nome
@nome = nome
end
end
class Programador < Empregado; end
class Restodopessoal < Empregado; end
Restodopessoal.new('Martins').guardar
Restodopessoal.new('Roberta').guardar
Programador.new('Eurico').guardar
puts Restodopessoal.exemplares.size
puts 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 Empregado
class << self; attr_accessor :exemplares; end
def guardar
self.class.exemplares || = []
self.class.exemplares << self
end
def initialize nome
@nome = nome
end
end
class Programador < Empregado; end
class Restodopessoal < Empregado; end
Restodopessoal.new('Martins').guardar
Restodopessoal.new('Roberta').guardar
Programador.new('Eurico').guardar
puts Restodopessoal.exemplares.size
puts 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