1

Why can I call a private method via Object#send(:private_method)?

What is the purpose of Ruby's private keyword if not to prevent direct calling of certain methods?

Is there anyway to reliably prevent objects from being able to call certain methods?

class Person
  def say_hi
    "hi"
  end

  private
  def private_say_hi
    "private hi"
  end
end

me = Person.new
me.say_hi
#=> "hi"

me.private_say_hi
#Error: private method `private_say_hi' called for #<Person:0x00558df4b79a08>

me.send(:private_say_hi)
#=> "private hi"
avtomate
  • 139
  • 1
  • 8
  • When designing an interface, a private method can be used to indicate that the method is unstable and should not be used directly by an object. – Sagar Pandya Oct 17 '17 at 23:24
  • It's doesn't maintain full use of the send method, and sets off a warning message, but here is an example of overriding the send method to prevent access to a private method: [link](https://stackoverflow.com/questions/20639857/how-to-disable-a-certain-method-in-ruby-from-being-called-in-the-console) – Pend Oct 18 '17 at 00:40
  • You will need to override a lot of things... https://stackoverflow.com/questions/5349624/how-to-call-methods-dynamically-based-on-their-name/26284769#26284769 You may be able to do a cheap check regarding the caller... – Brad Werth Oct 18 '17 at 00:43
  • FWIW, you might have better luck with "Is there anyway to reliably prevent objects from being able to call certain methods?" as the title of the question, and edit your question to comply with the theme. Of course, then it is probably just a dupe of https://stackoverflow.com/questions/20639857/how-to-disable-a-certain-method-in-ruby-from-being-called-in-the-console. As it is right now, it is broad and opinion based... – Brad Werth Oct 18 '17 at 00:44
  • Better that they can be called, anyway, otherwise the stymied programmer will simply copy/paste the code into the new location. Then you would have two problems... – Brad Werth Oct 18 '17 at 00:47

1 Answers1

2
  • Why can I call a private method via Object#send(:private_method)?

Look carefully at what you did:

me.send(:private_say_hi)

In nowhere the method private_say_hi is called in the form:

me.private_say_hi

That is why. Isn't is obvious?

  • What is the purpose of Ruby's private keyword if not to prevent direct calling of certain methods?

Just as the definition says. To avoid being called with an explicit receiver.

  • Is there anyway to reliably prevent objects from being able to call certain methods?

Use undef, undef_method, or remove_method depending on you needs.

sawa
  • 165,429
  • 45
  • 277
  • 381