Souza Lucas - Ruby: Aprenda a programar na linguagem mais divertida стр 15.

Шрифт
Фон

# 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.

Ваша оценка очень важна

0
Шрифт
Фон

Помогите Вашим друзьям узнать о библиотеке