Предположим, у меня есть следующий класс, как я могу получить доступ к переменной var
Переменные, идентификатор которых начинается со строчной буквы, локальные переменные . Локальные переменные являются локальными для области, в которой они определены, поэтому они называются «локальными» переменными.
Заданная вами переменная - это просто скучная старая стандартная локальная переменная, как и любая другая локальная переменная. В этом нет ничего особенного или особенного. К нему можно получить доступ, как и к любой другой локальной переменной: просто записав ее имя.
Например:
class Test
var = "value"
puts var # See? Nothing special, just like any other local variable.
end
# value
Последнее выражение, вычисленное внутри тела определения модуля, является значением модуля. определение выражения, чтобы вы могли извлечь содержимое переменной следующим образом:
another_local_variable = class Test
var = "value"
var
end
another_local_variable
#=> "value"
Вы также можете получить доступ к локальной переменной во вложенных областях. Опять же, в этом нет абсолютно ничего особенного или отличного. Это просто локальная переменная, которая ведет себя точно , как и любая другая локальная переменная, которую вы, возможно, уже использовали.
Единственные конструкции в Ruby, которые создают вложенные области видимости, - это блоки и лямбда-литералы. Итак, вы можете сделать что-то вроде этого:
class Test
var = "value"
define_method(:m1) do var end
define_singleton_method(:m2) do var end
end
Test.new.m1 #=> "value"
Test.m2 #=> "value"
Если вы можете получить доступ к объекту Binding
(используя метод Kernel#binding
) для лексическая область действия, в которой определена локальная переменная, затем вы можете получить ее значение, используя Binding#local_variable_get
:
b = class Test
var = "value"
binding
end
b.local_variable_get(:var) #=> "value"
Но опять же, я должен повторить: ничто в этом нет ничего особенного. Эта локальная переменная ведет себя на 100% точно так же, как любая другая локальная переменная . Локальная переменная - это просто локальная переменная.
Локальные переменные очень полезны в Ruby, потому что они являются языковой конструкцией only , которая обеспечивает идеальную инкапсуляцию. Все другие средства инкапсуляции в Ruby (переменные экземпляра, private
и т. Д. c.) Могут быть обойдены с помощью отражение (например, с использованием Object#instance_variable_get
или Object#send
), и отражение всегда доступно каждому без контроля доступа.
Но если кто-то явно не предоставит вам объект Binding
, локальные переменные не могут быть доступным за пределами их локального охвата. Раньше это было очень полезно для реализации этого шаблона:
class Foo
def bar
'Hello'
end
end
class Foo
old_bar = instance_method(:bar)
define_method(:bar) do
old_bar.bind(self).() + ' World'
end
end
Foo.new.bar # => 'Hello World'
Вы можете узнать больше об этом шаблоне в этом моем ответе под заголовком Метод Wrapping : { ссылка }
Несмотря на то, что этот специфический c шаблон устарел с введением Module#prepend
, существуют другие подобные ситуации, где он все еще полезен, например, для запоминания.