【问题标题】:redefining a single ruby method on a single instance with a lambda使用 lambda 在单个实例上重新定义单个 ruby​​ 方法
【发布时间】:2010-10-22 15:03:30
【问题描述】:

在 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

谢谢。

【问题讨论】:

    标签: ruby oop


    【解决方案1】:

    我不确定这是在哪个版本的 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 课程)时了解了这一点。 我仍然不完全确定这样做的目的是什么,因为这对我来说似乎有点危险。

    【讨论】:

    • 感谢您发布这个(更多)最新答案!
    • 假设 str.to_spanish 已经定义并且我想“重新定义”它,我如何从新定义的str.to_spanish 中调用“原始”str.to_spanish
    • 如果str是你的实例对象,String是你的类,你可以通过String.to_spanish调用类的方法版本
    • 上帝我爱鲁比
    【解决方案2】:

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

    str1 = "Hello"
    str2 = "Foo"
    
    class <<str1
      def to_spanish
        'Hola'
      end
    end
    

    现在如果您执行str1.to_spanish,它将返回“Hola”,但str2.to_spanish 会给您一个NoMethodFound 异常。

    【讨论】:

    • 如果他在一个简单的变量中有一个外部定义的proc,很难将它放入class创建的新范围
    【解决方案3】:
    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
    

    This question is highly related

    【讨论】:

    • 想知道为什么最后一个解决方案“可能不符合您的需求”?
    • 两者:``` class Foo end obj = Foo.new class
    • @AbdulRahmanK 因为他问如何使用 lambda 来实现,而这种方式不使用 lambda,但我还是想包含它
    猜你喜欢
    • 2017-12-18
    • 2013-11-20
    • 2010-09-13
    • 2023-02-24
    • 2012-07-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-02
    相关资源
    最近更新 更多