11 purchase.distance = 200
12
13 purchase.calculate_shipping_cost
14
15 purchase.shipping_cost # Qual é o valor?
Se você percebeu o mistério, já deve estar duvidando que shipping_cost seja
100. De fato, o valor não é 100 e sim nil. Mas qual a razão? Na linha 5, o Ruby
simplesmente interpreta a associação como a criação de uma variável local, ao in-
vés de procurar uma chamada de método de escrita. Portanto, é imprescindível que,
quando usarmos acessors de escrita sejam acompanhados de self. Observe que aces-
sors de leitura não necessitam dessa correção.
1 class Purchase
2
attr_accessor :shipping_cost, :weight, :distance
3
4
def calculate_shipping_cost
5
self.shipping_cost = distance * weight
6
end
7 end
8
9 purchase = Purchase.new
10 purchase.weight = 0.5
11 purchase.distance = 200
12
13 purchase.calculate_shipping_cost
14
15 purchase.shipping_cost # Agora sim, 100.0!
55
2.6. Classes e módulos
Casa do Código
Declarando métodos de classe
Não vimos anteriormente mas é possível declarar método em qualquer objeto,
não apenas uma classe. Vejamos o seguinte exemplo:
a = "123"
def a.scream
puts "AAAAAAAARGH!"
end
a.scream # "AAAAAAAARGH!"
b = "abc"
b.scream # NoMethodError: undefined method `scream' for "abc":String
Usamos essa mesma ideia para declarar métodos de classe:
1 class Purchase
2
attr_accessor :shipping_cost, :weight, :distance
3
4
def Purchase.build_free_shipping
5
purchase = new
6
purchase.shipping_cost = 0
7
8
purchase
9
end
10 end
11
12 Purchase.build_free_shipping # #<Purchase:0x0...0 @shipping_cost=0>
Métodos de classe executam no escopo de classe (ou seja, self é a própria classe),
então métodos como o construtor (como na linha 5 no exemplo anterior) são aces-
síveis sem ter que especificar a própria classe.
Porém, podemos melhorar isso. Dentro do bloco class, self é a própria classe.
Por isso, ao invés de termos que repetir o nome da classe, podemos usar simples-
mente self:
class Purchase
puts self # Purchase
def self.build_free_shipping
#...
56
Casa do Código
Capítulo 2. Conhecendo Ruby
end
end
Herança
Impossível falar sobre uma linguagem orientada a objetos sem mencionar he-
rança. Herança nada mais é do que a especialização de uma classe, muitas vezes
mudando apenas alguns comportamentos pontuais e ainda mantendo algumas ca-
racterísticas fundamentais, como nome de método.
class Shipping
attr_accessor :distance, :dimension
def cost
cubed_weight_factor = 16.7
distance * dimension/1000 * cubed_weight_factor
end
end
class UltraShipping < Shipping
def cost
super + (distance) * 0.07
end
end
shipping = UltraShipping.new
shipping.distance = 200
shipping.dimension = 1.2
shipping.cost # 18.00800...
No exemplo anterior, é possível perceber que, independente se usarmos
Shipping ou UltraShipping, o código vai funcionar pois ambas as classes respon-
dem aos mesmos métodos.
Este comportamento é possível através de duas características importantes da
linguagem. A primeira é a declaração de herança, usando <. Em seguida, vimos
também como é possível chamar métodos de mesmo nome da super classe usando
o super. O super é bastante importante para dizer ao Ruby que ele deve buscar na
Árvore Genealógica da classe (classe mãe, classe avó e assim vai) o método a ser
executado.
57
2.6. Classes e módulos
Casa do Código
Lembrando também que construtores (new) nada mais do que são métodos, en-
tão também são herdados!
Visibilidade de métodos
É muito importante quebrar seu código em vários métodos. Porém, muitas ve-
zes eles servem apenas para uso interno dentro das classes, portanto é importante
declará-lo como private, ou seja, métodos apenas acessíveis internamente à classe:
class Invoice
attr_accessor :service
def total_price
service + tax
end
private
def tax
service * 0.008
end
end
invoice = Invoice.new
invoice.service = 1000
invoice.total_price # 1008.00
invoice.tax # NoMethodError: private method `tax'
#
called for #<Invoice:0x007fdf92810550 @service=1000>
Diferente de muitas linguagens em que private ou public é prefixado à decla-
ração de todos os métodos, no Ruby funciona como uma chave que começa ligada
no public. Quando você então escreve private, a chave é virada e todos os méto-
dos então declarados são privados. Você pode voltar a chave para público chamando
public.
Métodos privados também são acessíveis de classes filhas. Isso pode ser uma
surpresa para você leitor, pois este comportamento não é comum. Dessa forma, não
é necessário usar protected para que classes filhas tenham acesso a esses métodos.
Fique atento a isso!
58
Casa do Código
Capítulo 2. Conhecendo Ruby
protected
O protected existe em Ruby e frequentemente é usado erroneamente devido ao
seu comportamento em outras linguagens. A real utilidade do protected é pratica-
mente nula e portanto deve ser evitada.
Mas para você, desenvolvedor curioso, fica a explicação do protected: o funci-
onamento do protected é quase o mesmo do private, contudo, é possível que um