Hoje vou falar um pouco a respeito de variáveis de instância em classes no
Ruby e seus métodos
de acesso.
No
Ruby, diferentemente do Java, todas as variáveis de instância tem controle de acesso
private, ou seja, só são acessíveis (escrita ou leitura)
diretamente para os métodos dentro da própria classe.
Para explicar melhor o porque isso é uma boa característica da linguagem, vou falar a respeito de acoplamento entre classes.
Em orientação a
objetos falamos que acoplamento entre classes é o nível em que uma classe tem acesso aos dados de outra. O ideal é que as classes tenham baixo
acoplamento entre si, isso é,
acessem as variáveis das outras classes apenas
através dos métodos disponíveis por ela (encapsulamento).
Vou dar um exemplo de uma relação de classes com alto acoplamento (característica não recomendada) em Java:


Nesse exemplo temos a classe A e a classe B. A classe B contém um
objeto do tipo A.
Note na
linha 6 da classe B que ela
acessa diretamente a variável de instância
name da classe A, uma vez que ela tem nível de acesso
public.
Esse tipo de relacionamento pode vir a trazer problemas futuramente, especialmente para a classe B, caso a classe A troque o nome da variável de instância
name, ou algo do
gênero.
O recomendado nesse caso seria que a variável
name tivesse nível de acesso
private e a classe disponibilizasse métodos para que classes externas
acessem essa variável.
Como no exemplo abaixo:


Dessa vez a classe B utiliza o método
setName da classe A para alterar a informação desejada. Dessa forma a classe A pode alterar sua lógica interna futuramente, sem precisar se preocupar com as classes que se relacionam com ela, portanto que ela mantenha os métodos
getName e
setName funcionando
corretamente.
Isso é um exemplo de baixo acoplamento entre classes, e essa é a boa prática.
Como eu estava dizendo, no
Ruby as variáveis de instância são sempre
privates, o que nos força a trabalhar da forma certa, fornecendo métodos
getters e
setters para
interação com outras classes.
Na verdade existem métodos como o
instance_variable_get, que retorna o valor de uma variável de
instância, mas métodos como esse só devem ser usados em caso de extrema necessidade. Para o nosso texto, vamos utilizar os métodos
getters e
setters.
Então toda vez que eu criar uma classe tenho que construir métodos
getters e
setters para cada uma das variáveis de
instância que eu desejar deixar disponível para leitura ou escrita por outras classes?
Na teoria sim, mas o
Ruby possui alguns métodos que nos ajudam bastante para esse tipo de tarefa, são eles :
attr_accessor,
attr_reader e
attr_writer.
Por exemplo, vou criar uma classe
User, dessa vez em
Ruby, que possua as variáveis de instância
name e
age, as quais eu vou permitir que qualquer outra classe leia e altere seus valores (portanto vou criar métodos
getters e
setters).

Para
acessar os dados das variáveis de instância de um
objeto dessa classe seria dessa forma:

Por enquanto lembra um pouco o Java, certo?
Agora vamos usar uma técnica bem interessante. Vamos nomear os métodos
getters com o mesmo nome da variável e os métodos
setters com o nome seguido de um sinal de igual (=), veja o exemplo:

Agora podemos
acessar os valores de um
objeto dessa classe da seguinte forma:

Isso é possível graças há uma grande característica do
Ruby chamada
Syntactic Sugar, que torna possível a criação de códigos mais amigáveis. No caso do exemplo acima o
Ruby nos permite adicionar um espaço antes e depois do sinal de igual e não usar parênteses para invocar o método.
Agora vamos falar sobre a parte interessante. Na verdade todo esse trabalho não precisa ser feito se eu for apenas criar métodos que permitam acesso ao conteúdo de uma variável.
Existe um método chamado
attr_accessor que faz todo esse trabalho para nós (cria a variável de instância e os métodos
getters e
setters para ela).
Para isso basta eu chamar o método e passar como parâmetros o nome dos campos que eu desejo que sejam minhas variáveis de instância. No caso de nosso exemplo, ficaria da seguinte forma:

E poderíamos
acessar os dados da mesma forma que no outro exemplo:

Como dito acima, o método
attr_accessor cria métodos de acesso para leitura e escrita das variáveis de instância passadas a ele. Para os casos em que precisamos criar apenas os métodos de leitura ou escrita, usamos os métodos
attr_reader e
attr_writer, em seu lugar.
Bom pessoal, essa foi mais uma pequena contribuição no blog para o pessoal que deseja aprender mais sobre a linguagem
Ruby, a qual eu recomendo e encorajo o aprendizado.
Para ler mais a respeito visitem a
API do
ruby e procurem pelos métodos
attr_accessor,
attr_reader,
attr_writer e
attr.
Gostaria de agradecer ao
Fábio Kung que me tirou dúvidas a respeito desse
post e está sempre me ajudando por e-mail.
Espero que o
post ajude, qualquer dúvida ou crítica podem mandar e-
mails ou postar comentários.
Até o próximo
post.
Abraços!