Understanding ‘self’ in Ruby

Today i’d like to talk about self. Se você tem estado programando Ruby por um tempo, você provavelmente internalizou a idéia de self. Sempre que você lê ou escreve um programa, self está lá na parte de trás de sua mente.

mas para Rubistas menos experientes, self pode ser desconcertante. Está sempre a mudar, mas nunca aparece explicitamente no código. Espera-se que saibas.

muitos dos problemas que os principiantes enfrentam são causados por não entender self. Se você já “perdeu” uma variável de instância ou intrigado sobre quais dados são visíveis para uma mixin, então é porque você não entendeu self nesse contexto.

neste post, vamos olhar para self em uma variedade de situações de cada dia.

o que é o self?Você pode ter ouvido as pessoas dizerem que tudo em Ruby é um objeto. Se isso é verdade, significa que cada pedaço de código que escreves pertence a algum objecto.

self é uma variável especial que aponta para o objeto que “possui” o código atualmente em execução. Ruby usa self everwhere:

  • por exemplo, variáveis: @myvar
  • para método e pesquisa constante
  • ao definir métodos, classes e módulos.

em teoria, self é bastante óbvio. Mas na prática, é fácil para situações complicadas aparecerem. Foi por isso que escrevi este post.

exemplos de self

vamos passar por vários exemplos agora. Se as primeiras parecerem demasiado básicas para ti, continua a ler. Eles ficam mais avançados.

Inside of an instance method

In the code below, reflect is an instance method. Pertence ao objeto que criamos via Ghost.new. Então self aponta para esse objeto.

class Ghost def reflect self endendg = Ghost.newg.reflect == g # => true

dentro de um método de classe

para este exemplo, reflect é um método de classe Ghost. Com métodos de classe, A própria classe “possui” o método. self aponta para a classe.

class Ghost def self.reflect self endendGhost.reflect == Ghost # => true

funciona da mesma forma com métodos de” classe ” dentro dos módulos. Por exemplo:

module Ghost def self.reflect self endend Ghost.reflect == Ghost # => true

lembre-se, classes e módulos são tratados como objetos em Ruby. Então esse comportamento não é assim tão diferente do método de instância que vimos no primeiro exemplo.

dentro de uma definição de classe ou módulo

uma característica do Ruby que o torna tão adequado para frameworks como trilhos é que você pode executar código arbitrário dentro de classes e definições de módulos. Quando você coloca o código dentro de uma definição de classe / módulo, ele corre como qualquer outro código Ruby. A única diferença real é o valor self.

como pode ver abaixo, self aponta para a classe ou módulo que está em processo de ser definido.

class Ghost self == Ghost # => trueend module Mummy self == Mummy # => trueend 

Inside mixin methods

Mixed-in methods behave just like “normal” instance or class methods when it comes to self. Faz sentido. Caso contrário, a mistura não seria capaz de interagir com a classe em que a misturou.

Instance methods

Even though the reflect method was defined in the module, its self is the instance of the class it was mixed into.

module Reflection def reflect self endend class Ghost include Reflectionendg = Ghost.newg.reflect == g # => true

métodos de Classe

Quando nós extend uma classe para misturar em métodos de classe, self comporta-se exatamente como ele faz em condições normais de métodos de classe.

module Reflection def reflect self endend class Ghost extend ReflectionendGhost.reflect == Ghost # => true

dentro do metaclass

é provável que tenha visto este atalho popular para definir muitos métodos de classe de uma vez.

class Ghost class << self def method1 end def method2 end endend

a sintaxe class << foo é realmente muito interessante. Permite-lhe aceder ao metaclass de um objecto-que também é chamado de “classe singleton” ou “eigenclass”.”Planeio cobrir metaclasses mais profundamente num post futuro. Mas por agora, você só precisa saber que o metaclass é onde a Ruby armazena métodos que são únicos para um objeto específico. Se aceder a self do interior do bloco class << foo, obtém-se o metaclass.

class << "test" puts self.inspectend# => #<Class:#<String:0x007f8de283bd88>

Fora de qualquer classe

Se você estiver executando o código fora de qualquer classe, Ruby ainda fornece self. Aponta para “main” , que é um exemplo de Object:

puts self.inspect # => main