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