4

次のコードで、2 種類の呼び出しメソッドに違いがあるのはなぜですか。

class Access
    def method_missing name
        print "Method is missing"
    end

    protected
    def protected_method
        print "Calling Protected Method"
    end
end

access = Access.new
access.protected_method #Method is missing
access.send(:protected_method) #Calling Protected Method

期待どおりにaccess.protected_method動作します。ただし、sendオプションは、保護されていてもメソッドを呼び出そうとします。内部で何が起こっているのか知りたいです。

メソッドを呼び出すための文字列を取得するので、使用sendしたいのですが、保護されたメソッドを呼び出したくありません。

4

4 に答える 4

6

それがまさに仕組みsendです。public_sendpublic メソッドのみを呼び出したい場合は、代わりに使用してください。

于 2012-09-19T13:13:00.200 に答える
1

send を使用すると、オブジェクトの保護またはプライベート メソッドへのアクセスなど、一部のルールをバイパスできます。

もう 1 つのことは、send を使用すると、メソッドを動的に呼び出すことができるということです。send を使用すると、プログラムの実行前に知らずにどのメソッドが呼び出されるかを決定できます。つまり、実行時に渡されるメッセージを決定できます。

それ以外は、私の知る限り、それらは同じです。

于 2012-09-19T13:00:16.243 に答える
0

まあ、それはどのように機能するかsendです。可視性に関係なく、メソッドを呼び出すことができます。存在しない名前を送信すると、が起動method_missingします。参照:

class Access
    def method_missing name
        "Method is missing"
    end

    protected
    def protected_method
        "Calling Protected Method"
    end
end

access = Access.new
access.protected_method # => "Method is missing"
access.send(:protected_method) # => "Calling Protected Method"
access.send(:non_existing_method) # => "Method is missing"

保護されたメソッドがこのように呼び出されたくない場合は、恐ろしいのにこれは良いユースケースだと思いevalます。

eval "Access.new.protected_method" # => "Method is missing"
eval "Access.new.non_existing_method" # => "Method is missing"
于 2012-09-19T13:02:23.253 に答える
-1

の用途の 1 つはsend可視性をバイパスすることです。これはバグではなく機能であり、実際、この動作を許可しないと、クラスを使用する他のプログラマーの期待を裏切る可能性があります。

そうは言っても、本当に必要な場合は、オーバーライドsendmethod_missingて、クラスで必要な動作を実装できます。

class Access
  def foo; puts "foo"; end

  def method_missing(message, *args)
    puts "Method #{message} missing"
  end

  def send(message, *args)
    if self.class.protected_instance_methods.include?(message)
      method_missing(message, *args)
    else
      super
    end
  end

protected

  def bar; puts "bar"; end
end

a = Access.new
a.foo            #=> 'foo'
a.bar            #=> 'Method bar missing'
a.send('bar')    #=> 'Method bar missing'
于 2012-09-19T13:06:21.613 に答える