An áttekintés a blokkok végrehajtási környezetéről
Ebben a cikkben a következő témákat fogjuk megvizsgálni:
- scopes and blocks
- flat scope guard in class/module
Először is bátran böngészd át a Scope Gates in Ruby: Part II cikket.
Befejezés előtt
Örömömre szolgál, hogy megoszthatom veled legújabb projektünket: Fun Facts about Ruby – Volume 1
Kérem, nyugodtan terjessze a hírt és ossza meg ezt a linket! 🙏
Köszönjük, hogy időt szakított ránk!
A Rubyban egy blokk hozzáférhet a külső hatókörhöz
Ebben a példában a outer_scope_variable
változóhoz férünk hozzá a blokkunkon belül. A blokkunk akkor is hozzáférhet ehhez a változóhoz, ha a változót main
szintű hatókörben deklaráltuk. Ebben az esetben azt mondjuk, hogy a blokk laposítja a hatóköröket. Ezért szoktuk ezt a mechanizmust így hívni: Flat Scope.
A másik oldalon a blokk izolált hatóköröket hoz létre – még akkor is, ha a self
értéke a blokkon belül a main
objektum marad.
Ezért a blokkon belül definiált helyi változókat nem tudjuk elérni
Ezért a block_variable
-hoz nem tudunk hozzáférni a külső hatókörből. Most, hogy jobban megismertük a lapos hatókör fogalmát a Rubyban, nézzük meg, hogy ez a fogalom befolyásolja-e az osztálydefiníciót.
osztály, modul és blokk
A Rubyban az, amit általában osztálynak hívunk, a színfalak mögött a Class
osztály egy példánya
Itt a Hello
és Greeting
osztályokat két különböző módon hozzuk létre:
- a
class
kulcsszó használatával - azzal, hogy a
Class
osztály egy példányát hozzárendeljük aGreeting
konstanshoz
Megjegyezzük, hogy a Class.new
metódusnak egy blokkot adunk át. Ez a blokk az osztály tartalmaként lesz értelmezve. Normális esetben egy osztály nem férhet hozzá a külső hatókörben definiált változókhoz – mivel a class
kulcsszó megváltoztatja a self
értékét, és létrehoz egy izolált hatókört.
Mivel tehát egy blokkot használunk a Greeting
osztályunk létrehozásához, akkor a flat scope mechanizmust kell tudnunk használni. Valóban?
Itt láthatjuk, hogy a self
értéke megváltozik, ha a class
vagy a Class.new
kulcsszót használjuk.
Az Class#message
blokkunk a def
kulcsszó használata miatt továbbra is izolált a main
objektumtól. Valóban, mivel a blokkunk a metódus kontextusában kerül végrehajtásra, akkor a blokk az adott objektumon belül – és nem egy magasabb hatókörrel, mint a main
objektum.
Ez az oka annak, hogy a message
-on belül nem férünk hozzá a outer_variable
-hez.
De ha a define_method
-t használjuk a message
definiálására, akkor a hatókör ellaposodik
Mivel a define_method(:message)
egy blokkot vesz argumentumként, ennek a blokknak a hatókörét ellaposítjuk, és ez a metódus hozzáfér outer_variable
-hez.
Voilà!