Ruby Object Model – self
Leia em 1 minuto
Quando você decidiu aprender Ruby, ficou sabendo que tudo é objeto; números, classes, módulos… tudo, sem exceção, é realmente um objeto. Só que isso traz algumas implicações que nem todos conhecem. A ideia é fazer com que você realmente entenda a essência de Ruby em uma série de artigos sobre o Ruby Object Model e Metaprogramming.
Entendendo o self
self
será sempre uma referência ao receiver atual e pode ser diferente dependendo do contexto em que você estiver. Por exemplo, quando estamos no namespace global, nosso self
será o objeto main
. Já em uma classe, nosso self
será a própria classe.
puts self
#=> main
class Thing
puts self
end
#=> Thing
Sempre que executar um método, o Ruby irá verificar se esse método existe no receiver padrão—self
— a menos que você especifique-o explicitamente. E, pelo fato de o receiver padrão ser self
, você nem precisa especificá-lo se não quiser.
class Thing
def do_something
puts "doing something"
end
def do_something_else
do_something
end
end
No método do_something_else
poderíamos usar self.do_something
, mas isso faria com que nosso código apenas ficasse mais poluído. No entando, definir o receiver é uma coisa muito comum e que, você pode até não se dar conta, mas o faz constantemente quando escreve código Ruby.
numbers = [3,1,2]
numbers.sort
#=> [1,2,3]
ou ainda
text = "some string"
text.upcase
#=> "SOME STRING"
Na prática, o receiver é especificado antes do ponto na chamada de métodos, como em numbers.sort
ou text.upcase
.
Além de ser o receiver padrão, self
também é o responsável por armazenar variáveis de instância de um objeto. Veja o exemplo abaixo.
class Person
def initialize(name)
@name = name
end
def name
@name
end
end
john = Person.new("John Doe")
john.name
#=> "John Doe"
A instância da classe Person
possui uma única variável de instância associada ao seu objeto—self
—que é retornada pelo método name
. Analogamente, podemos definir variáveis de instância em qualquer objeto, como classes.
class Person
def self.count
@count ||= 0
end
def self.count=(increment)
@count = increment
end
def initialize(name)
@name = name
self.class.count += 1
end
def name
@name
end
end
john = Person.new("John Doe")
Person.count
#=> 1
O exemplo acima mostra como variáveis de instância podem ser usadas em contextos diferentes. Primeiro, estamos definindo um contador de instâncias da classe Person
, cujo valor será armazenado em @count
. Depois, em nossa própria instância, definimos o nome com a variável @name
.
Finalizando
No próximo artigo, irei falar sobre metaclasses do Ruby. Até lá!