The difference between accessing a protected method directly and using send

Why is there a difference between the two types of calling methods in the following code:

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 works as expected. But the send parameter tries to call the method, even if it is protected. I would like to know what is happening inside the country.

I get a string for the method being called, so I would like to use send , but I don't want to call protected methods.

+4
source share
4 answers

This is how send works. Use public_send if you only want to call public methods.

+6
source

Using send allows you to bypass some rules, such as access to protected or private methods of an object.

Another thing is that send allows you to dynamically call methods. Using send, you can decide which methods to call without knowing it before the program starts, that is, you can decide which message will be sent to it at run time.

In addition, as far as I know, they are the same.

+1
source

Good thing send works. This allows you to call a method regardless of its visibility. If you submit a nonexistent name, then method_missing will be pressed. See:

 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" 

If you do not want your protected methods to be called this way, then I think this is a good precedent for the dreaded eval .

 eval "Access.new.protected_method" # => "Method is missing" eval "Access.new.non_existing_method" # => "Method is missing" 
0
source

One way to use send is to bypass visibility, so this is a function, not an error, and in fact you are likely to break the expectations of other programmers using your class if you do not allow this behavior.

However, if you really need it, you can override send and method_missing in your class to implement the desired behavior:

 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' 
-1
source

Source: https://habr.com/ru/post/1435057/


All Articles