У меня есть тестовый класс и класс коробки, в тестовом классе у меня есть переменная с именем boxHolder, которая представляет собой массив, я хочу переопределить метод ‹* для этого массива. Как я могу получить доступ к moski_call внутри синглтона?
class Test
attr_accessor :boxHolder
def initialize()
super
self.boxHolder = Array.new
class << @boxHolder
def <<(box)
box.setPositionWithinColumn(moski_call)
super(box)
end
end
end
def moski_call
"YAAAAAAAAAAAAAAAAAAAA"
end
end
class Box
def initialize
end
def setPositionWithinColumn(str)
puts "got a string #{str}"
end
end
# test
box = Box.new
test = Test.new
test.boxHolder
Ответ 1 · horseyguy
нравится:
# need this or else `moski_call` method is looked up in context of @boxholder
moski_call_output = moski_call
class << @boxholder; self; end.send(:define_method, :<<) { |box|
box.setPositionWithinColumn(moski_call_output)
super(box)
}
Ответ 2 · Edu
Как насчет:
def self.boxHolder.<< (box)
box.setPositionWithinColumn(moski_call)
super(box)
end
Это объявит метод для вашего экземпляра boxHolder. Но boxHolder не имеет доступа к методу moski_call
Ответ 3 · Marc-André Lafortune
Вам необходимо сохранить доступ к "родительскому" объекту Test. Это можно сделать, используя тот факт, что блоки являются замыканиями:
parent = self # to be accessible in the closure
@boxHolder.define_singleton_method(:<<) do |box|
box.setPositionWithinColumn(parent.moski_call)
super(box)
end
Примечание: define_singleton_method является новым в Ruby 1.9, поэтому либо обновите, require 'backports/1.9.1/kernel/define_singleton_method', либо сделайте class << @boxHolder; define_method(:<<){ "..." } end при использовании более старого Ruby.