Es posible en Ruby para obtener una referencia a los métodos de un objeto ( me gustaría saber si esto se puede hacer sin procs/lambdas ) , por ejemplo , considere el siguiente código :


class X
  def initialize
    @map = {}
    setup_map
  end

  private
  def setup_map
    # @map["a"] = get reference to a method
    # @map["b"] = get reference to b method
    # @map["c"] = get referebce to c method
  end

  public
  def call(a)
    @map["a"](a) if a > 10
    @map["b"](a) if a > 20
    @map["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

Es posible hacer tal cosa ? Me gustaría evitar procs/lambdas porque quiero ser capaz de cambiar el comportamiento de a,B,C por subclases .

InformationsquelleAutor Geo | 2009-01-27

4 Comentarios

  1. 46

    Desea 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"

    Ahora el código se convierte en:

    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
    • Genial!!! Usted es el hombre 🙂
  2. 4

    Usted puede hacer esto con lambdas, mientras que el mantenimiento de la capacidad para cambiar el comportamiento en subclases:

    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
    • Esto funciona ! Pero , no hay manera de obtener una referencia a un método ?
    • Lo mejor que podría hacer es instancia.métodos y que da una matriz de cadenas.
  3. 1

    Métodos de Ruby no son objetos de primera clase, donde se implementa OO con el paso de mensajes.

    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

    O simplemente llame a ellos directamente:

    def call(a)
      self.a(a) if a > 10
      self.b(a) if a > 20
      self.c(a) if a > 30
    end
    • Este era un simple ejemplo . Para las clases que necesito para escribir , voy a tener unos 20-30 métodos de verificación . Si comprueba que no sería muy elegante , ¿verdad ?
    • Supuse que el si-declaraciones fueron apoderados de un interruptor o de un hash de búsqueda. «send(:un, una)» parece más simple que el de «@map[«a»][arg]» para mí, más aún si hay muchos de ellos.
  4. 0

    Puede obtener una referencia al método por el object.method(:method_name).

    Por ejemplo: para obtener una referencia A system método.

    m = self.method(:system)
    m.call('ls)

Dejar respuesta

Please enter your comment!
Please enter your name here