Photo by Jack Anstey on Unsplash

An przegląd kontekstu wykonania bloków

Mehdi Farsi

Follow

Sep 20, 2019 – 3 min read

W tym artykule będziemy badać następujące tematy:

  • zakresy i bloki
  • flat scope guard w klasie/module

Na początek zapraszam do przejrzenia artykułu Scope Gates in Ruby: Part II article.

Zanim zaczniemy

Jestem zachwycony mogąc podzielić się z Tobą naszym najnowszym projektem: Fun Facts about Ruby – Volume 1

Please feel free to spread the word and share this link! 🙏

Dziękuję za Twój czas!

W Rubim, blok może uzyskać dostęp do zewnętrznego zakresu

W tym przykładzie, możemy uzyskać dostęp do zmiennej outer_scope_variable wewnątrz naszego bloku. Nasz blok uzyskuje dostęp do tej zmiennej, mimo że zmienna jest zadeklarowana w zakresie poziomu main. W tym przypadku mówimy, że blok spłaszcza zakresy. Dlatego też potocznie nazywamy ten mechanizm: Flat Scope.

Z drugiej strony, blok tworzy izolowany zakres – nawet jeśli wartość self w obrębie bloku pozostaje obiektem main.

Nie mamy więc dostępu do zmiennych lokalnych zdefiniowanych w obrębie bloku

Tutaj nie mamy dostępu do block_variable z zewnętrznego zakresu. Teraz, gdy jesteśmy bardziej zaznajomieni z pojęciem płaskiego zakresu w Rubim, zobaczmy czy to pojęcie ma wpływ na definicję klasy.

Klasa, moduł i blok

W Rubim, to co powszechnie nazywamy klasą jest, za sceną, instancją klasy Class

Tutaj tworzymy klasy Hello i Greeting na dwa różne sposoby:

  • używając słowa kluczowego class
  • przypisując instancję klasy Class do stałej Greeting

Zauważ, że przekazujemy blok do metody Class.new. Blok ten zostanie zinterpretowany jako zawartość klasy. Normalnie klasa nie może mieć dostępu do zmiennych zdefiniowanych w zewnętrznym zakresie – ponieważ słowo kluczowe class zmienia wartość self i tworzy izolowany zakres.

Więc, skoro używamy bloku do stworzenia naszej klasy Greeting to powinniśmy móc korzystać z mechanizmu płaskiego zakresu. Naprawdę?

W tym miejscu widzimy, że wartość self zmienia się, gdy używamy class lub Class.new.

Ale nasz blok Class#message jest nadal odizolowany od obiektu main z powodu użycia słowa kluczowego def. W istocie, ponieważ nasz blok jest wykonywany w kontekście metody, wtedy blok spłaszcza zakres w obrębie tego danego obiektu – a nie z wyższym zakresem jak obiekt main.

Dlatego nie mamy dostępu do outer_variable w obrębie message.

Ale jeśli użyjemy define_method do zdefiniowania message to zakres jest spłaszczony

Tutaj, ponieważ define_method(:message) przyjmuje blok jako argument, zakres tego bloku jest spłaszczony i ta metoda ma dostęp do outer_variable.

Voilà!

.

Articles

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany.