質問

動的メソッド呼び出しの使用 (#send または #method) メソッドの可視性は無視されます。
プライベートメソッドの呼び出しに失敗するメソッドを動的に呼び出す簡単な方法はありますか?

役に立ちましたか?

解決

ご存じのとおり、public_sendメソッドが必要です:

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

他のヒント

public_send を使用します送信ではなく

my_object.public_send :method, *args

Ruby 1.9の新機能です。古いRubyの場合、 require 'backports / 1.9.1 / kernel / public_send '

Ruby-1.9 を使用している場合は、次を使用できます Object#public_send それはあなたが望むことをします。

Ruby-1.8.7 以前を使用している場合は、独自のコードを作成する必要があります。 Object#public_send

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

なぜそうするのか理解できないと思いますが、 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

本当ですが、evalは実際に1.9より前に実際に行う唯一の方法だと思います。可視性について詳しく知りたい場合は、Jamis Buckが素晴らしい記事を書きました Rubyでメソッドの可視性が実際に意味するものについて。

Rubyの可視性は、他の言語と非常にわずかに異なります。

避けたい場合は eval, send または public_send, 、またはあなたが望む よりよい性能, 、 使用 public_method 方法:

obj.public_method('my_method_name').call

次のように引数を追加できます。

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

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top