Ну, один из способов сделать это - упаковать его в переменную экземпляра:
(К вашему сведению, вы можете просто сделать class Thing
, чтобы открыть Thing
(это немного короче, чем использование #class_eval
, и вам не нужно #instance_eval
для определения методов внутри метода).
class Thing
def speak
puts "This is the instance method referenced by the Thing object #{self}"
r = "something I wish to hold on to, maybe expensive to calculate"
@l = lambda {puts r}
instance_eval do
def speak()
puts "This is the singleton method in the Thing object #{self}"
@l[]
end
end
end
end
Это переопределит #speak
, но только для этого экземпляра Thing
. Другие экземпляры Thing
будут по-прежнему иметь первоначальное определение.
Альтернативой, как указал Чак, является использование одноэлементного класса (он же метакласс, он же собственный класс), связанного с экземпляром. Класс singleton - это объект, в котором хранятся все одноэлементные методы, связанные с объектом. Вы можете получить контекст для оценки одноэлементного класса, используя забавный синтаксис class <<object ; ... ; end
(аналогично контексту, заданному #class_eval
обычными классами).
class Thing
def speak
puts "This is the instance method referenced by the Thing object #{self}"
r = "something I wish to hold on to, maybe expensive to calculate"
singleton_class = class <<self # open singleton class context for current instance
# in this context, self now refers to the singleton class itself
self
end
l = lambda {puts r}
singleton_class.class_eval do
# since we used #class_eval, local variables are still in scope
define_method(:speak) do
puts "This is the singleton method in the Thing object #{self}"
# since we used #define_method, local variables are still in scope
l[]
end
end
end
end