переопределение одного метода ruby ​​для одного экземпляра с помощью лямбды - PullRequest
32 голосов
/ 29 апреля 2009

В 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

Спасибо.

Ответы [ 3 ]

45 голосов
/ 29 апреля 2009
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

или, если вы хотите определить свой прок, встроенный, это может быть более читабельным

class << y
  define_method(:bar, proc { "foobar!" })
end

или

class << y
  define_method(:bar) { "foobar!" }
end

это наиболее читаемый, но, вероятно, не соответствует вашим потребностям

def y.bar
  "goodbye"
end

Этот вопрос очень связан

25 голосов
/ 19 мая 2013

Я не уверен, в какой версии 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). Я все еще не совсем уверен, какова цель этого, так как это кажется мне немного опасным.

16 голосов
/ 30 апреля 2009

Вы можете использовать синтаксис class <<object, чтобы получить «синглтон-класс» объекта (это специальный родительский класс, принадлежащий только этому объекту) и определить методы только для этого экземпляра. Например:

str1 = "Hello"
str2 = "Foo"

class <<str1
  def to_spanish
    'Hola'
  end
end

Теперь, если вы сделаете str1.to_spanish, он вернет "Hola", но str2.to_spanish выдаст вам исключение NoMethodFound.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...