Comprendre le ‘soi’ dans Ruby

Aujourd’hui, j’aimerais parler de self. Si vous programmez Ruby depuis un moment, vous avez probablement intériorisé l’idée de self. Chaque fois que vous lisez ou écrivez un programme, self est là dans le fond de votre esprit.

Mais pour les Rubyistes moins expérimentés, self peut être déroutant. Cela change toujours, mais cela n’est jamais explicitement affiché dans le code. On s’attend à ce que tu le saches.

Beaucoup de problèmes auxquels les débutants sont confrontés sont causés par une compréhension insuffisante de self. Si vous avez déjà « perdu » une variable d’instance ou si vous vous demandez quelles données sont visibles par un mixin, c’est parce que vous ne compreniez pas self dans ce contexte.

Dans cet article, nous allons examiner self dans une variété de situations quotidiennes.

Qu’est-ce que le soi?

Vous avez peut-être entendu des gens dire que tout dans Ruby est un objet. Si c’est vrai, cela signifie que chaque morceau de code que vous écrivez « appartient » à un objet.

self est une variable spéciale qui pointe vers l’objet qui « possède » le code en cours d’exécution. Ruby utilise self partout:

  • Par exemple variables: @myvar
  • Pour la méthode et la recherche constante
  • Lors de la définition de méthodes, de classes et de modules.

En théorie, self est assez évident. Mais dans la pratique, il est facile pour les situations délicates d’apparaître. C’est pourquoi j’ai écrit ce post.

Exemples de soi

Nous allons maintenant passer en revue plusieurs exemples. Si les premiers semblent trop basiques pour vous, continuez à lire. Ils deviennent plus avancés.

À l’intérieur d’une méthode d’instance

Dans le code ci-dessous, reflect est une méthode d’instance. Il appartient à l’objet que nous avons créé via Ghost.new. Donc self pointe vers cet objet.

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

À l’intérieur d’une méthode de classe

Pour cet exemple, reflect est une méthode de classe de Ghost. Avec les méthodes de classe, la classe elle-même « possède » la méthode. self pointe vers la classe.

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

Cela fonctionne de la même manière avec les méthodes « classe » à l’intérieur des modules. Par exemple:

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

N’oubliez pas que les classes et les modules sont traités comme des objets dans Ruby. Donc, ce comportement n’est pas si différent du comportement de la méthode d’instance que nous avons vu dans le premier exemple.

À l’intérieur d’une définition de classe ou de module

Une caractéristique de Ruby qui convient si bien aux frameworks comme Rails est que vous pouvez exécuter du code arbitraire à l’intérieur des définitions de classe et de module. Lorsque vous mettez du code à l’intérieur d’une définition de classe / module, il s’exécute comme n’importe quel autre code Ruby. La seule différence réelle est la valeur de self.

Comme vous pouvez le voir ci-dessous, self pointe vers la classe ou le module en cours de définition.

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

Dans les méthodes mixin

Les méthodes mixtes se comportent comme des méthodes d’instance ou de classe « normales » en ce qui concerne self. Cela a du sens. Sinon, le mixin ne pourrait pas interagir avec la classe dans laquelle vous l’avez mélangé.

Méthodes d’instance

Même si la méthode reflect a été définie dans le module, sa self est l’instance de la classe dans laquelle elle a été mélangée.

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

Méthodes de classe

Lorsque nous extend une classe à mélanger dans des méthodes de classe, self se comporte exactement comme dans les méthodes de classe normales.

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

Dans la métaclasse

, il y a de fortes chances que vous ayez vu ce raccourci populaire pour définir de nombreuses méthodes de classe à la fois.

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

La syntaxe class << foo est en fait assez intéressante. Il vous permet d’accéder à la métaclasse d’un objet – également appelée « classe singleton » ou « classe propre ». »Je prévois de couvrir plus profondément les métaclasses dans un prochain article. Mais pour l’instant, il vous suffit de savoir que la métaclasse est l’endroit où Ruby stocke des méthodes uniques à un objet spécifique.

Si vous accédez à self depuis le bloc class << foo, vous obtenez la métaclasse.

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

En dehors de toute classe

Si vous exécutez du code en dehors d’une classe, Ruby fournit toujours self. Il pointe vers « main », qui est une instance de Object:

puts self.inspect # => main