代码之家  ›  专栏  ›  技术社区  ›  Emirikol

如何在尊重隐私的同时动态调用方法

  •  6
  • Emirikol  · 技术社区  · 16 年前

    使用动态方法调用( #send 或 #method )方法的可见性被忽略。
    有没有一种简单的方法来动态调用一个方法,它将无法调用私有方法?

    6 回复  |  直到 9 年前
        1
  •  12
  •   andrykonchin    16 年前

    如我所知-你需要公共方法发送:

    ----------------------------------------------------- Object#public_send
         obj.public_send(symbol [, args...])  => obj
    
         From Ruby 1.9.1
    ------------------------------------------------------------------------
         Invokes the method identified by _symbol_, passing it any arguments
         specified. Unlike send, public_send calls public methods only.
    
            1.public_send(:puts, "hello")  # causes NoMethodError
    
        2
  •  6
  •   Marc-André Lafortune    13 年前

    使用 public_send 而不是 send :

    my_object.public_send :method, *args
    

    它是Ruby1.9的新特性,所以对于旧的Ruby,您可以 require 'backports/1.9.1/kernel/public_send' .

        3
  •  3
  •   johannes    16 年前

    如果您使用的是Ruby-1.9,则可以使用 Object#public_send 这就是你想要的。

    如果您使用Ruby-1.8.7或更早版本,则必须编写自己的 对象\公共\发送

    class Object
      def public_send(name, *args)
        unless public_methods.include?(name.to_s)
          raise NoMethodError.new("undefined method `#{name}' for \"#{self.inspect}\":#{self.class}")
        end
        send(name, *args)
      end
    end
    

    或者你可以自己写 Object#public_method 表现得像 Object#method 但只适用于公共方法

    class Object
      def public_method(name)
        unless public_methods.include?(name.to_s)
          raise NameError.new("undefined method `#{name}' for class `#{self.class}'")
        end
        method(name)
      end
    end
    
        4
  •  0
  •   Simone Carletti    16 年前

    我想我不明白你为什么要这样做,你可以用 eval .

    class Klass
      private
        def private_method(arg)
        end
    end
    
    k = Klass.new
    m = "private_method"
    eval "k.#{m}('an arg')"
    
    NoMethodError: private method `private_method' called for #<Klass:0x128a7c0>
        from (irb):15
        from (irb):15
    
        5
  •  0
  •   Chuck Vose    16 年前

    但这是真的,埃瓦尔真的是我认为唯一的方法,真正做到1.9之前。如果你想了解更多关于能见度的信息,杰米斯巴克写了一篇 awesome article 关于Ruby中的方法可见性实际上意味着什么。

    就像Ruby可见性中的其他东西一样,它与其他语言有着微小的不同。

        6
  •  0
  •   Brad Werth    11 年前

    如果你想避免 eval , send 或 public_send ,或者你想要 better performance 使用 public_method method :

    obj.public_method('my_method_name').call

    您可以添加如下参数:

    obj.public_method('my_method_name').call('some_argument_1', 'some_argument_2')