使用lambda在单个实例上重新定义单个ruby方法

kmo*_*511 33 ruby oop

在Ruby中,有没有办法使用proc重新定义类的特定实例的方法?例如:

class Foo
  def bar()
    return "hello"
  end
end

x = Foo.new
y = Foo.new
Run Code Online (Sandbox Code Playgroud)

(就像是):

y.method(:bar) = lambda { return "goodbye" }

x.bar
y.bar
Run Code Online (Sandbox Code Playgroud)

生产:

hello
goodbye
Run Code Online (Sandbox Code Playgroud)

谢谢.

Joh*_*hat 46

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)
Run Code Online (Sandbox Code Playgroud)

或者,如果你想猴子修补对象以使其变得容易

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
Run Code Online (Sandbox Code Playgroud)

或者,如果您想定义proc内联,这可能更具可读性

class << y
  define_method(:bar, proc { "foobar!" })
end
Run Code Online (Sandbox Code Playgroud)

要么,

class << y
  define_method(:bar) { "foobar!" }
end
Run Code Online (Sandbox Code Playgroud)

这是最具可读性的,但可能不适合您的需求

def y.bar
  "goodbye"
end
Run Code Online (Sandbox Code Playgroud)

这个问题高度相关

  • @AbdulRahmanK 因为他问如何使用 lambda 来做到这一点,并且这种方式不使用 lambda,但我还是想包含它 (2认同)

Pat*_*ick 26

我不确定添加了什么版本的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
Run Code Online (Sandbox Code Playgroud)

在阅读Ruby Koans(about_class_methods.rb课程)的同时学到了这一点.我仍然不完全确定这是什么目的,因为它对我来说似乎有点危险.


Chu*_*uck 16

您可以使用语法class <<object来获取对象的"单例类"(这是仅属于该对象的特殊父类),并仅为该实例定义方法.例如:

str1 = "Hello"
str2 = "Foo"

class <<str1
  def to_spanish
    'Hola'
  end
end
Run Code Online (Sandbox Code Playgroud)

现在,如果你这样做str1.to_spanish,它将返回"Hola",但str2.to_spanish会给你一个NoMethodFound异常.