2016-08-01 8 views
0

Для драгоценного камня Я работаю над тем, что мне нужно добавить переменную в main, желательно локальную переменную, но экземпляр также работает. Я пытаюсь использовать Object.instance_variable_set, но не добился такого прогресса. Как я могу это сделать?Добавить переменную в основную

Разъяснение

Мне нужно установить переменную экземпляра из модуля в main.

Вот моя ситуация:

module MyGem::Submodule 
    def self.add_variable_to_main 
     Object.instance_variable_set(:@var,"value") 
    end 
    def self.recieve_variable_from_main 
     Object.instance_variable_get(:@var) 
    end 
    def self.store_block 
     @@block=&block 
    end 
    def self.call_block 
     add_variable_to_main 
     @@block.call 
     puts recieve_variable_from_main 
    end 
end 

class Object 
    include MyGem::Submodule 
end 

store_block do 
    @var = "Var is #{@var}" 
end 

call_block 

Я также спросил this question о той же проблеме, она имеет дополнительные детали.

+3

'main' - это контекст' TOPLEVEL_BINDING', вы действительно уверены, что именно здесь вы хотите добавить это? Объясните пример использования, который не будет так же легко обрабатываться глобальным объектом или константой верхнего уровня. Драгоценный камень должен быть инкапсулированной библиотекой, а мутация верхнего уровня может иметь непреднамеренные результаты. – engineersmnky

+0

@engineersmnky В моем драгоценном камне мне нужно установить переменную, доступную в основном, но делать это, хотя объект будет работать так же хорошо. Не могли бы вы написать ответ, объясняющий недостатки и хорошие альтернативы? – thesecretmaster

+0

Можете ли вы привести пример того, чего вы надеетесь достичь? Я думаю, вы неправильно поняли концепцию 'main' – engineersmnky

ответ

4

main - объект, объекты не могут иметь локальные переменные. Локальные переменные относятся к лексическим областям, а не к объектам.

Вы можете просто присвоить переменной экземпляра в контексте main:

@ivar = 42 

Теперь main имеет экземпляр переменной @ivar со значением 42.

Object#instance_variable_set работает точно так же:

instance_variable_set(:@ivar, 42) 

Если вы не в контексте main, вы можете получить доступ верхнего уровня Binding через глобальную постоянную TOPLEVEL_BINDING и сам main объект через TOPLEVEL_BINDING.receiver, так как main неявная приемник, т.е. self на высшем уровне:

module Foo 
    TOPLEVEL_BINDING.receiver.instance_variable_set(:@ivar, 42) 
end 

@ivar # => 42 
+0

Это не решает мою проблему, потому что моя проблема в том, что я должен установить ее из модуля в 'main', потому что это gem, и мне нужно установить переменную за кулисами для пользователя, так что это не работает для меня. – thesecretmaster

+0

Это работает? –

+0

Я думаю, что это сработает, я просто воздерживаюсь от принятия ответа, пока не сделаю немного больше исследований. – thesecretmaster

2

Существует константа TOPLEVEL_BINDING, которая хранит привязку main. Вы можете установить переменные экземпляра в main из любой точки с привязкой.

module Foo 
    TOPLEVEL_BINDING.eval '@foo = :bar' 
end 

@foo #=> :bar 
Смежные вопросы