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á!

Comentários #

#1 Tweets that mention Ruby Object Model – self — Simples Ideias... disse:
29 Set 10, 11:06AM

[...] This post was mentioned on Twitter by Diego R. V., Carlos Antonio and emerson vinicius, Vinícius Oliveira. Vinícius Oliveira said: RT @cantoniodasilva: primeiro artigo de uma série sobre ruby object model e metaprogramming ~ http://bit.ly/ahMdSD (via @fnando) [...]

#2 mairon disse:
29 Set 10, 11:15AM

parabens pela iniciativa

abraco

#3 Emerson Vinicius disse:
29 Set 10, 12:53PM

Belo post.
quer dizer que quando faço isso
class Person
def self.count
@count ||= 0
end
end

estou definindo count a Class Person e não ao meu objeto é isso?

#4 Nando Vieira disse:
29 Set 10, 04:24PM

Isso mesmo! A variável de instância sempre estará atrelada a um objeto representado pelo self e que neste caso é uma classe.

#5 Ruby Object Model – Singleton Class — Simples Ideias. Por... disse:
30 Set 10, 10:30AM

[...] artigo anterior eu mostrei como o self muda em diferentes contextos. Neste artigo, você verá o que são as [...]

Deixe um comentário





Não é aceito código HTML: adicione-o no pastie.org ou paste.milk-it.net e poste apenas o link.

Se este é seu primeiro comentário, ele terá que ser aprovado antes de ser exibido.

JavaScript Avançado

O JavaScript é a única linguagem que muitos acreditam saber sem nunca terem parado para realmente aprendê-la. Neste workshop rápido você entenderá de verdade todos os conceitos avançados do JavaScript em 4 horas puramente práticas.

Saiba mais Fechar

Conheça também o HOWTO