sfery widoczności, takie jak pokoje w domu
kiedy rozmawialiśmy o zmiennych, wspomnieliśmy, że najczęstszym typem zmiennych jest „zmienna lokalna”, nie wyjaśniając dalej, Dlaczego są lokalne. Do czego? Gdzie? W końcu jesteśmy gotowi to wyjaśnić.
ponieważ mówiliśmy już o metodach, możemy również omówić inny ważny koncept: zakresy.
Wikipedia mówi: „w programowaniu zakres nazwy jest częścią programu, w którym nazwa jest prawidłowa: gdzie nazwa może być używana do odniesienia się do czegoś.”
nazwy są znane (lub zdefiniowane) w pewnym zakresie, a nieznane (lub niezdefiniowane) poza tym zakresem.
możesz myśleć o zakresie jako o kuli, bańce lub pokoju (z teraz oknami i zamkniętymi drzwiami): niektóre nazwy, takie jak nazwy zmiennych, są „znane” i”widoczne” wewnątrz pokoju. Inne nazwiska, znane i widoczne w innym pomieszczeniu, nie są znane w tym pokoju, ale tylko w drugim pokoju.
za każdym razem, gdy jest wywołanie metody, a przepływ wykonania wchodzi do ciała thethod, wchodzi w nowy zakres, czyli „pokój”. Rzeczy, które są” lokalne „do zakresu tej metody (tj. rzeczy, które są” wewnątrz ” pomieszczenia), są tylko widoczne w tym zakresie. Poza tym są nieznane.
Undefined local variable or method
jest to również dobra okazja, aby porozmawiać o komunikacie o błędzie, który widzisz najczęściej. Na przykład zobaczysz go za każdym razem, gdy popełnisz literówkę i źle napisałeś nazwę zmiennej lub metody.
rozważ ten kod:
def add_two(number) number + 2endputs add_two(3)puts number
liniaputs add_two(2)
wyprowadzi5
, ale liniaputs number
spowoduje błąd.
dzieje się tak dlatego, że zmiennanumber
, której przypisany jest numer3
, gdy wecall metoda jest zmienną lokalną. Jest lokalny w zakresie metody. Jest tworzony, gdy przepływ wykonania wchodzi do metody.
poza tym zakresem, gdy przepływ wykonania powrócił z metodzie zakres metody został zniszczony, a wszystkie zmienne lokalne zniknęły. Zmienna lokalna number
nie jest zatem znana, a Ruby wyświetla błąd o treściundefined local variable or method 'number'
.
Jeśli myślisz o tym komunikacie o błędzie przez chwilę, czy ma to dla ciebie sens?
po cichu pominęliśmy fakt, że w Rubim zarówno lokalne nazwy zmiennych, jak i nazwy metod, są zapisywane w ten sam sposób: są to zwykłe słowa.Na przykład, tutaj:
number = 2puts number
number
jest zmienną lokalną i jest używana w wierszu puts number
.
jednak tutaj:
def number 2endputs number
number
jest nazwą metody. I może być użyta (wywołana) dokładnie tak samo: puts number
dzieje się tak dlatego, że Ruby, gdy wykonuje program, przetwarza jedną instrukcję po drugiej. A kiedy napotka zwykłe słowo ,takie jaknumber
, to najpierw sprawdzi, czy w bieżącym zakresie zna zmienną lokalną o takiej samej nazwie. Jeśli tak, użyje wartości powiązanej z tą zmienną. Jeśli nie ma zmiennej lokalnej o tej nazwie, wtedy będzie szukać metody. Jeśli nie ma również metody o tej nazwie, wyświetli komunikat o błędzie undefined local variable or method 'number'
.
więc komunikat o błędzie jest dość precyzyjny, ale również brzmi trochę zawile. Co w zasadzie próbuje powiedzieć:
użyłeś tutaj słowa „Liczba”, a ja go nie znam (w tym zakresie). Chciałeś użyć zmiennej lokalnej? Czy metoda?
czy to ma sens?
powrót do tematu lokalne zakresy. Spójrzmy na inny przykład:
number = 1def add_to(number) number + 2endputs add_to(3)
jak myślisz, jakie będzie wyjście? Czy będzie to 3
, czy 5
? Coś jeszcze?
Po uruchomieniu kodu zobaczysz, że jest to5
.
powodem tego jest to, że przypisujemy numer 1
w zewnętrznym zakresie do avariable number
, ale ta zmienna nigdy nie jest używana: jedyną inną linią w zewnętrznym zakresie jest ostatnia linia puts add_to(3)
, a ta linia nie używa zmiennej number
.
zamiast tego, gdy przepływ sterowania wejdzie do metodyadd_to
Ruby utworzy nowy lokalny zakres i zdefiniuje nową zmienną lokalnąnumber
, która jest przypisana numerowi3
, który został przekazany do metody. Ta nowa zmiennanumber
jest lokalna dla zakresu metody i dlatego jest to zmienna inna niż ta w pierwszej linii, w zewnętrznym zakresie.
znaleźliśmy następującą dobrą metaforę dla zakresów:
Kiedy Ruby wchodzi do metody, to tak, jakby weszła do lśniącego nowego pokoju w pomieszczeniu. Wraz z nią przynosi przedmioty, które są przekazywane jako argumenty do wywołania. W powyższym przykładzie przynosi obiekt o numerze 3
.
teraz, gdy tylko Ruby wejdzie do metody, przykleja notatki post-it na obiektach, zgodnie z listą argumentów z definicji metody. W naszym przykładzie jest to nazwa number
. Więc od teraz, w tym pokoju, jest znana zmienna lokalna, która ma przypisaną wartość: obiekt (numer) 3
z notatką number
na nim.
w naszym przykładzie, zewnętrzny zakres i zakres metody add_two
, są dwa różne pokoje i są dwa różne notatki post-it przyklejone do dwóch różnych numerów, które tak się składa, że mają tę samą nazwę.