Переопределение одного рубинового метода на одном экземпляре с лямбдой
В Ruby существует способ переопределить метод конкретного экземпляра класса с помощью proc? Например:
class Foo
def bar()
return "hello"
end
end
x = Foo.new
y = Foo.new
(Что-то вроде):
y.method(:bar) = lambda { return "goodbye" }
x.bar
y.bar
Производство:
hello
goodbye
Спасибо.
Ответы
Ответ 1
def define_singleton_method_by_proc(obj, name, block)
metaclass = class << obj; self; end
metaclass.send(:define_method, name, block)
end
p = proc { "foobar!" }
define_singleton_method_by_proc(y, :bar, p)
или, если вы хотите, чтобы объект обезьяны-патча упрощался
class Object
# note that this method is already defined in Ruby 1.9
def define_singleton_method(name, callable = nil, &block)
block ||= callable
metaclass = class << self; self; end
metaclass.send(:define_method, name, block)
end
end
p = proc { "foobar!" }
y.define_singleton_method(:bar, p)
#or
y.define_singleton_method(:bar) do
"foobar!"
end
или, если вы хотите определить свой встроенный proc, это может быть более читаемым
class << y
define_method(:bar, proc { "foobar!" })
end
или,
class << y
define_method(:bar) { "foobar!" }
end
это наиболее читаемый, но, вероятно, не соответствует вашим потребностям
def y.bar
"goodbye"
end
Этот вопрос сильно связан
Ответ 2
Я не уверен, какая версия Ruby была добавлена в (как минимум 1.8.7), но, похоже, еще более простой способ сделать это:
str1 = "Hello"
str2 = "Goodbye"
def str1.to_spanish
"Hola"
end
puts str1 # => Hello
puts str1.to_spanish # => Hola
puts str2 # => Goodbye
puts str2.to_spanish # => Throws a NoMethodError
Узнал об этом во время чтения Ruby Koans (about_class_methods.rb урок).
Я все еще не совсем уверен, в чем цель этого, так как мне кажется немного опасным.
Ответ 3
Вы можете использовать синтаксис class <<object
для получения объекта "singleton class" (который является особым родительским классом, принадлежащим только этому объекту) и определять методы только для этого экземпляра. Например:
str1 = "Hello"
str2 = "Foo"
class <<str1
def to_spanish
'Hola'
end
end
Теперь, если вы сделаете str1.to_spanish
, он вернет "Hola", но str2.to_spanish
предоставит вам исключение NoMethodFound.