How can I get a reference to a method?

前端 未结 4 464
花落未央
花落未央 2021-01-07 16:32

Is it possible in Ruby to get a reference to methods of an object ( I would like to know if this can be done without procs/lambdas ) , for example , consider the following c

相关标签:
4条回答
  • 2021-01-07 16:59

    You can do this with lambdas while maintaining the ability to change behavior in subclasses:

    class X
      def initialize
        @map = {}
        setup_map
      end
    
      private
      def setup_map
        @map["a"] = lambda { |a| a(a) }
        @map["b"] = lambda { |a| b(a) }
        @map["c"] = lambda { |a| c(a) }
      end
    
      public
      def call(a)
        @map["a"].call(a) if a > 10
        @map["b"].call(a) if a > 20
        @map["c"].call(a) if a > 30
      end
    
      def a(arg)
         puts "a was called with #{arg}"
      end
    
      def b(arg)
         puts "b was called with #{arg}"
      end
    
      def c(arg)
        puts "c was called with #{arg}"
      end
    end
    
    0 讨论(0)
  • 2021-01-07 17:05

    You can get a reference to the method by object.method(:method_name).

    Eg: To get a reference to system method.

    m = self.method(:system)
    m.call('ls')
    
    0 讨论(0)
  • 2021-01-07 17:10

    Ruby methods aren't first-class objects; it implements OO with message passing.

    class X
      def call(a)
        self.send(:a, a) if a > 10
        self.send(:b, a) if a > 20
        self.send(:c, a) if a > 30
      end
    
      def a(arg)
         puts "a was called with #{arg}"
      end
    
      def b(arg)
         puts "b was called with #{arg}"
      end
    
      def c(arg)
        puts "c was called with #{arg}"
      end
    end
    

    Or just call them directly:

    def call(a)
      self.a(a) if a > 10
      self.b(a) if a > 20
      self.c(a) if a > 30
    end
    
    0 讨论(0)
  • 2021-01-07 17:14

    You want Object#method:

    ---------------------------------------------------------- Object#method
         obj.method(sym)    => method
    ------------------------------------------------------------------------
         Looks up the named method as a receiver in obj, returning a Method 
         object (or raising NameError). The Method object acts as a closure 
         in obj's object instance, so instance variables and the value of 
         self remain available.
    
            class Demo
              def initialize(n)
                @iv = n
              end
              def hello()
                "Hello, @iv = #{@iv}"
              end
            end
    
            k = Demo.new(99)
            m = k.method(:hello)
            m.call   #=> "Hello, @iv = 99"
    
            l = Demo.new('Fred')
            m = l.method("hello")
            m.call   #=> "Hello, @iv = Fred"
    

    Now your code becomes:

    private
    def setup_map
      @map = {
        'a' => method(:a),
        'b' => method(:b),
        'c' => method(:c)
      }
      # or, more succinctly
      # @map = Hash.new { |_map,name| _map[name] = method(name.to_sym) }
    end
    
    public
    def call(arg)
      @map["a"][arg] if arg > 10
      @map["b"][arg] if arg > 20
      @map["c"][arg] if arg > 30
    end
    
    0 讨论(0)
提交回复
热议问题