redefining a single ruby method on a single instance with a lambda

后端 未结 3 2134
半阙折子戏
半阙折子戏 2020-12-04 18:30

In Ruby, is there a way to redefine a method of a particular instance of a class using a proc? For example:

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


        
相关标签:
3条回答
  • 2020-12-04 18:42

    You can use the syntax class <<object to get an object's "singleton class" (that's a special parent class belonging only to that object) and define methods only for that instance. For example:

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

    Now if you do str1.to_spanish, it will return "Hola", but str2.to_spanish will give you a NoMethodFound exception.

    0 讨论(0)
  • 2020-12-04 18:53

    I'm not sure what version of Ruby this was added in (at least 1.8.7), but there seems to be an even simpler way of doing this:

    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
    

    Learnt about this whilst reading the Ruby Koans (about_class_methods.rb lesson). I'm still not entirely sure what the purpose of this is since it seems a bit dangerous to me.

    0 讨论(0)
  • 2020-12-04 18:55
    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)
    

    or, if you want to monkey-patch Object to make it easy

    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
    

    or, if you want to define your proc inline, this may be more readable

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

    or,

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

    this is the most readable, but probably doesn't fit your needs

    def y.bar
      "goodbye"
    end
    

    This question is highly related

    0 讨论(0)
提交回复
热议问题