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