An aperçu du contexte d’exécution des blocs
Dans cet article, nous allons explorer les sujets suivants :
- scopes et blocs
- garde de scope plat en classe/module
D’abord, n’hésitez pas à parcourir les portes de scope en Ruby : Partie II article.
Avant de commencer
Je suis ravi de partager avec vous notre dernier projet : Fun Facts about Ruby – Volume 1
N’hésitez pas à faire passer le mot et à partager ce lien ! 🙏
Merci pour votre temps!
En Ruby, un bloc peut accéder à la portée extérieure
Dans cet exemple, nous pouvons accéder à la variable outer_scope_variable
à l’intérieur de notre bloc. Notre bloc a accès à cette variable même si la variable est déclarée à une portée de niveau main
. Dans ce cas, on dit que le bloc aplatit les scopes. C’est pourquoi nous appelons communément ce mécanisme : Flat Scope.
D’autre part, le bloc crée une portée isolée – même si la valeur de self
à l’intérieur du bloc reste l’objet main
.
On ne peut donc pas accéder aux variables locales définies à l’intérieur du bloc
Ici, nous ne pouvons pas accéder au block_variable
depuis la portée extérieure. Maintenant que nous sommes plus familiers avec la notion de flat scope en Ruby, voyons si cette notion a un impact sur la définition des classes.
Classe, module et bloc
En Ruby, ce que vous appelez communément une classe est, derrière la scène, une instance de la classe Class
Ici, nous créons les classes Hello
et Greeting
de deux manières différentes :
- en utilisant le mot-clé
class
- en assignant une instance de la classe
Class
à la constanteGreeting
Notez que nous passons un bloc à la méthode Class.new
. Ce bloc sera interprété comme le contenu de la classe. Normalement, une classe ne peut pas accéder aux variables définies dans la portée externe – car le mot clé class
change la valeur de self
et crée une portée isolée.
Donc, comme nous utilisons un bloc pour créer notre classe Greeting
alors nous devrions pouvoir utiliser le mécanisme de portée plate. Vraiment ?
On voit ici que la valeur de self
change lorsqu’on utilise class
ou Class.new
.
De plus, notre bloc Class#message
est toujours isolé de l’objet main
grâce à l’utilisation du mot clé def
. En effet, comme notre bloc est exécuté dans le contexte de la méthode alors le bloc aplatit la portée au sein de cet objet donné – et non pas avec une portée plus élevée comme l’objet main
.
C’est pourquoi nous n’avons pas accès à outer_variable
au sein de message
.
Mais si nous utilisons define_method
pour définir message
alors la portée est aplatie
Ici, comme define_method(:message)
prend un bloc comme argument, la portée de ce bloc est aplatie et cette méthode a accès à outer_variable
.
Voilà!