Подтвердить что ты не робот

Переопределение одного рубинового метода на одном экземпляре с лямбдой

В 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

Спасибо.

4b9b3361

Ответ 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.