An overview of the execution context of blocks

În acest articol, vom explora următoarele subiecte:
- scoape și blocuri
- flat scope guard in class/module
În primul rând, nu ezitați să parcurgeți Scope Gates in Ruby: Partea a II-a.
Înainte de a începe
Sunt încântat să vă împărtășesc cel mai recent proiect al nostru: Fun Facts about Ruby – Volumul 1
Vă rugăm să nu ezitați să răspândiți vestea și să distribuiți acest link! 🙏
Mulțumim pentru timpul acordat!
În Ruby, un bloc poate accesa domeniul exterior
În acest exemplu, putem accesa variabila outer_scope_variable
în cadrul blocului nostru. Blocul nostru are acces la această variabilă, chiar dacă variabila este declarată la un domeniu de nivel main
. În acest caz, spunem că blocul aplatizează domeniile de cuprindere. Acesta este motivul pentru care numim în mod obișnuit acest mecanism: Flat Scope.
Pe de altă parte, blocul creează un scope izolat – chiar dacă valoarea lui self
în cadrul blocului rămâne obiectul main
.
Deci nu putem accesa variabilele locale definite în cadrul blocului
În acest caz, nu putem accesa block_variable
din scope-ul exterior. Acum că suntem mai familiarizați cu noțiunea de flat scope în Ruby, să vedem dacă această noțiune are un impact asupra definirii claselor.
Clasă, modul și bloc
În Ruby, ceea ce se numește în mod obișnuit o clasă este, în spatele scenei, o instanță a clasei Class
Aici, creăm clasele Hello
și Greeting
în două moduri diferite:
- folosind cuvântul cheie
class
- prin atribuirea unei instanțe a clasei
Class
la constantaGreeting
Rețineți că transmitem un bloc metodei Class.new
. Acest bloc va fi interpretat ca fiind conținutul clasei. În mod normal, o clasă nu poate accesa variabilele definite în domeniul de cuprindere exterior – deoarece cuvântul cheie class
schimbă valoarea lui self
și creează un domeniu de cuprindere izolat.
Atunci, deoarece folosim un bloc pentru a crea clasa noastră Greeting
, atunci ar trebui să putem folosi mecanismul domeniului de cuprindere izolat. Serios?
Aici putem vedea că valoarea lui self
se schimbă atunci când folosim class
sau Class.new
.
De asemenea, blocul nostru Class#message
este încă izolat de obiectul main
datorită folosirii cuvântului cheie def
. Într-adevăr, deoarece blocul nostru este executat în contextul metodei, atunci blocul își aplatizează domeniul de aplicare în cadrul acestui obiect dat – și nu cu un domeniu de aplicare mai mare ca obiectul main
.
De aceea nu avem acces la outer_variable
în cadrul message
.
Dar dacă folosim define_method
pentru a defini message
atunci domeniul de cuprindere este aplatizat
Aici, deoarece define_method(:message)
primește ca argument un bloc, domeniul de cuprindere al acestui bloc este aplatizat și această metodă are acces la outer_variable
.
Voilà!