Попробуйте использовать define_method. Def помещает вас в новую сферу.
class Test
def initialize(a)
@a = a
end
def item
item = "hola"
item.singleton_class.send(:define_method, :singl) do
[self, @a].join(" + ")
end
item
end
end
test = Test.new("cao")
item = test.item
item.singl #=> "hola + "
В вашем примере, тем не менее, у вас все еще есть проблема, внутри синглтон-класса строка @a не была определена. Это в первую очередь потому, что self в этом контексте является экземпляром строки, а не тестовым экземпляром, где существует @a
. Чтобы это исправить, вы можете привязать переменную экземпляра к чему-то другому, но это может быть не то поведение, которое вы ищете. Вы также можете установить переменную экземпляра в своем новом синглтон-классе.
Например,
Пересвязать переменную
class Test
def initialize(a)
@a = a
end
def item
item = "hola"
new_self = self
item.singleton_class.send(:define_method, :singl) do
[self, new_self.instance_variable_get(:@a)].join(" + ")
end
item
end
end
test = Test.new("cao")
item = test.item
item.singl
Установить строковую переменную экземпляра
class Test
def initialize(a)
@a = a
end
def item
item = "hola"
item.singleton_class.send(:define_method, :singl) do
[self, @a].join(" + ")
end
item.singleton_class.send(:define_method, :set) do
@a = "cao"
end
item
end
end
test = Test.new("cao")
item = test.item
item.set
item.singl
Важно отметить различия между этими двумя методами. В первом методе мы сохраняем ссылку на исходную переменную экземпляра через исходный объект. Во втором методе мы создаем новую переменную экземпляра, связанную с новым одноэлементным классом, содержащую копию исходного теста. @ A.
Если вы используете не родной объект, вы можете избежать сочетания обоих методов. Ссылка на объект старой переменной экземпляра с помощью новой переменной экземпляра классов singelton через указатель, но это не будет работать для int, string, float и т. Д. *
РЕДАКТИРОВАТЬ: Как отметил Бенуа, во втором методе метод "set" должен быть просто attr_accessor. Фактически, вы можете установить переменную экземпляра, не определяя новый метод вообще. Через item.instance_variable_set(:@, "cao")