self or no self

Ruby is sometimes very confusing. For example, when you call an instance method within the same class, you can do so with or without self... it's optional:

instance_method # works from inside the class
self.instance_method # also works from inside the class
other_object.instance_method # works from outside the class

However, if the method is a setter method, you must use self. The reasoning behind this is that Ruby doesn't know whether instance_method is an instance method or a local variable, and the self gets rid of that ambiguity. Let's call this rule A.

instance_method = 42 # error
self.instance_method = 42 # works

However, private methods can't use self. Let's call this rule B. The reasoning behind this is that private methods cannot be called with an explicit receiver, even if self is that receiver.

self.private_method # error
private_method # works

What happens when rule A butts head with rule B?

private_method = 42 # violates rule A - error
self.private_method = 42 # violates rule B - but works!

Apparently in this case, the second line is the one that's allowed. This blog post explains it very clearly:

When using a setter in Ruby we're supposed to use an explicit receiver like self. Here we have a private method that doesn't allow an explicit receiver. We appear to have reached an impasse. In this case it turns out Ruby breaks its own rule.
Before I found this, I was trying to get around the impasse by doing jenky things like this:

private_method=(42)

I was surprised this wasn't a bigger topic, but then I read this article about how private and protected methods aren't even used that much in Ruby!

For the most part, we just... don’t [write private methods].
The following is from the book I'm reading, Practical Object Oriented Design in Ruby by Sandi Metz:
Users of a class can redefine any method to public regardless of its initial declaration. The private and protected keywords are more like flexible barriers than concrete restrictions. ... Using them sends two messages:
  • You believe that you have better information today than programmers will have in the future
  • You believe that those future programmers need to be prevented from accidentally using a method that you currently consider unstable
These beliefs may be correct but the future is a long way off and one can never be certain... many perfectly  competent Ruby programmers omit them and instead use comments or a special method naming convention (Ruby on Rails, for example, adds a leading '_' to private methods) to indicate public and private parts of interfaces.
I don't know what I feel about all this yet, but I might skip over writing private methods for now just because it makes things much easier for me immediately.

Comments