Как разработчик Ruby, одной из фундаментальных концепций, которую нужно понимать, является переменная область — когда и где вы можете использовать переменные, созданные вами в программе. Некоторые из моих самых больших трудностей при написании программ на ранних этапах были в основном связаны с неполным пониманием того, как работает масштаб.
Опять же, область действия переменной указывает, где к ней можно получить доступ и использовать в программе. И эта область действия или «возможность использования» определяется тем, где создается сама переменная.
Переменные, инициализированные или созданные внутри блока, привязаны к этому конкретному блоку. Это ключевой момент, о котором следует помнить. После создания переменную можно использовать внутри этого блока сколько угодно раз.
weekdays = [‘Monday’, ‘Tuesday’, ‘Wednesday’, ‘Thursday’,’Friday’] phrase = “Thank God it’s” weekdays.each do |day| praise = “Amen, “ puts praise + phrase + “ “ + day end => Amen, Thank God it’s Monday => Amen, Thank God it’s Tuesday => Amen, Thank God it’s Wednesday => Amen, Thank God it’s Thursday => Amen, Thank God it’s Friday
Однако доступ к той же самой переменной невозможен из-за пределов блока, который находится вне его области действия.
puts praise => `<main>’: undefined local variable or method `praise’ for main:Object (NameError)
И наоборот, если переменная инициализируется вне блока, к ней можно получить доступ из блока. Обратите внимание, что наша переменная phrase в приведенном выше примере была создана таким образом, и мы смогли получить к ней доступ.
weekdays = [‘Monday’, ‘Tuesday’, ‘Wednesday’, ‘Thursday’,’Friday’] phrase = “Thank God it’s” weekdays.each do |day| praise = “Amen, “ puts praise + phrase + “ “ + day end
Также важно отметить, что циклы и блоки — это не одно и то же, и каждый из них ведет себя по-разному при обработке переменной. Тот факт, что к циклу присоединено do…end, может ввести в заблуждение. При определении области действия переменной блок представляет собой d0…end или набор фигурных скобок {подобно этим, которые следуют сразу за методом. Например:
weekdays.each do |day| puts day end OR weekdays.each{|day| puts day}
Поскольку цикл не является блоком, он не определяет область действия переменной. Это означает, что переменные, инициализированные внутри цикла некоторого типа, могут использоваться как внутри, так и вне цикла. Обратите внимание, что мы можем получить доступ к переменной greeting как внутри, так и вне цикла.
a = 0 while a < 4 greeting = “Wassup!?” puts a.to_s + “ “ + greeting a += 1 end puts greeting + " from outside!" => 0 Wassup!? => 1 Wassup!? => 2 Wassup!? => 3 Wassup!? => Wassup!? from outside!
Итак, это относится к блокам и циклическим конструкциям, а как насчет методов? Как они относятся к переменным в связи с областью видимости? К этому моменту мне понадобилось некоторое время, чтобы привыкнуть. Оказывается, в отличие от блоков и циклов, методы создают собственную область видимости, которая отделена от обычного потока выполнения программы.
Переменная, инициализированная в методе, относится к этому методу. К нему нельзя получить доступ извне метода. Кроме того, метод не может получить доступ к переменным, инициализированным вне его.
my_number = 7 def addition(number) number = 10 number + number end puts addition(my_number) puts my_number puts number => 20 => 7 =>`<main>': undefined local variable or method `number' for main:Object (NameError)
Здесь мы инициализируем переменную my_number и определяем новый метод с именем дополнение. Затем мы помещаем возвращаемое значение передачи my_number в метод дополнения. Обратите внимание, что на выходе 20, а не 14, хотя мы добавляем переменную к самой себе внутри метода. Почему это?
Ответом на это является то, что переменная my_number переименовывается в number при передаче в метод addition. Затем переменной number присваивается значение 10 внутри метода. Таким образом, (число + число) = (10 + 10) = 20. Во втором положении мы видим, что значение my_number былонеизменным и это все еще 7. Между тем, попытка доступа к переменной number вне метода сложения приводит к ошибке. Это связано с тем, что number привязан к методу добавления и не может использоваться вне его.
Важно отметить, что есть некоторые нюансы в том, как Ruby работает с переменными, которые передаются методам. А именно, является ли Ruby языком передачи по значению или передачи по ссылке (на самом деле это и то, и другое, шшш). Это целая «черная банка червей», о которой, возможно, я расскажу в новом посте. Но, надеюсь, эта небольшая заметка поможет кому-то лучше понять, как работает переменная область видимости.