# true
"um_simbolo_qualquer".object_id == "um_simbolo_qualquer".object_id
# false
Veja que independente da quantidade de vezes que referenciamos um símbolo,
ele sempre será o mesmo objeto (o método object_id retorna o um identificador
do objeto na memória). Já no caso das String, mesmo sendo exatamente iguais,
são objetos diferentes na memória. Como String são imutáveis, cada objeto tem
seu próprio espaço em memória, quando elas não são mais referenciadas, poderão
ser coletadas pelo coletor de lixo (Garbage Collector - GC).
Já os símbolos, por terem um única instância na memória, nunca serão coleta-
dos pelo GC. Além disso, símbolos não são guardados somente na memória, eles
também ficam em um dicionário de símbolos otimizado pelo interpretador.
3.6
Atributos nem tão privados assim
42
Casa do Código
Capítulo 3. O começo da nossa aplicação
3.6. ATRIBUTOS NEM TÃO PRIVADOS ASSIM
Umas das características de variáveis de instância é que elas são privadas, ou seja,
seu valor não pode ser alterado de fora da classe, apenas com métodos públicos que
internamente em sua implementação alteram o valor da variável. Vimos isso quando
precisamos alterar o valor da variável preco.
Infelizmente, existem maneiras de burlar estas restrições, e uma vez que temos
em mãos a instância de um objeto qualquer, podemos ler e alterar o valor das variá-
veis de instância.
teste_e_design = Livro.new "Mauricio Aniche", "123454", 247, 60.9
puts teste_e_design.instance_variable_get "@preco" # => 60.9
O método instance_variable_get retorna o valor de uma variável de ins-
tância qualquer. Basta passar como argumento o nome da variável com o @. No
código acima, o resultado será 60.9. Ler o valor da variável não é tão problemático
se compararmos com o fato de que podemos alterar o valor de qualquer variável de
instância também:
teste_e_design = Livro.new "Mauricio Aniche", "123454", 247, 60.9
teste_e_design.instance_variable_set "@preco", 75.5
puts teste_e_design.preco # => 75.5
O método instance_variable_set recebe dois argumentos, o primeiro é
o
nome da variável de instância que você deseja alterar, o segundo o valor que você
deseja atribuir à variável.
Os métodos instance_variable_set e instance_variable_get são
métodos herdados por todos os objetos Ruby. Eles pertencem a classe Object,
que é a classe pai da hierarquia de classes que temos na linguagem. Esses métodos
nos apesentam o começo de um assunto muito discutido e poderoso da linguagem
conhecido como meta-programação.
3.7
Grandes poderes, grandes responsabilidades
3.7. GRANDES PODERES, GRANDES RESPONSABILIDADES
Os métodos que vimos na seção anterior, podem parecer muito poderosos em uma
primeira impressão. Porém, com o tempo e dependendo do tamanho do projeto
43
Casa do Código
podem nos trazer grandes dores de cabeça. Vamos tomar como exemplo a nossa
classe Livro:
# coding: utf-8
class Livro
attr_accessor :preco
def initialize(autor, isbn = "1", numero_de_paginas, preco)
@autor = autor
@isbn = isbn
@numero_de_paginas = numero_de_paginas
@preco = preco
end
def to_s
"Autor: #{@autor}, Isbn: #{@isbn}, Páginas: #{@numero_de_paginas}"
end
end
Você sentindo-se o Peter Parker da vida real, resolve alterar o valor de alguma
variável usando o instance_variable_set:
teste_e_design = Livro.new "Mauricio Aniche", "123454", 247, 60.9
teste_e_design.instance_variable_set "@preco", 75.5
puts teste_e_design.preco # 75.5
Depois de alguns anos, você decide casar-se com Mary Jane e abandonar sua vida
de homem aranha e também o desenvolvimento de software. O projeto é assumido
por outro desenvolvedor que resolve alterar o nome da variável preco para valor:
# coding: utf-8
class Livro
attr_accessor :valor
def initialize(autor, isbn = "1", numero_de_paginas, valor)
@autor = autor
@isbn = isbn
@numero_de_paginas = numero_de_paginas
@valor = valor
end
def to_s
44
Casa do Código
Capítulo 3. O começo da nossa aplicação
"Autor: #{@autor}, Isbn: #{@isbn}, Páginas: #{@numero_de_paginas}"
end
end
teste_e_design = Livro.new "Mauricio Aniche", "123454", 247, 60.9
puts teste_e_design.preco
# => NoMethodError: undefined method `preco'
for Autor: Mauricio Aniche, Isbn: 123454, Páginas: 247:Livro
A chamada ao método preco retornará o erro: NoMethodError, obviamente
porque o método agora se chama valor:
teste_e_design = Livro.new "Mauricio Aniche", "123454", 247, 60.9
puts teste_e_design.valor
Porém o antigo desenvolvedor homem aranha deixou em algum lugar do sistema
uma chamada ao instance_variable_set:
teste_e_design.instance_variable_set "@preco", 75.5
puts teste_e_design.instance_variable_get "@preco"
O problema é que além de tentarmos alterar o valor da uma variável que não
existe mais, o código acima é silencioso, não retorna nenhum erro avisando que
aquela variável não existe, pelo contrário, ele cria uma variável nova chamada
@preco que não tem relação alguma com nosso domínio, já que quando a variá-
vel não existe, ao tentarmos acessá-la ela será criada.