Handling private methods is currently a bit messy.
The original rule:
private methods can be called without an explicit receiver.
This is a nice, simple, easy to understand rule. This is also a static rule, that is, it can be checked without running the code, in fact it is even a syntax rule, it does not even need complex static analysis, it can be checked in the parser.
However, it was soon noticed that this rule made it impossible to call private setters, since setters cannot be called without an explicit recipient ( foo = bar is a local variable parameter that does not call the setter). Ergo, the rule has been expanded:
Private methodscan only be called without an explicit receiver, if the method call is not an assignment method call, in which case the method can also be called with an explicit receiver, if this explicit receiver is a literal pseudo-variable self .
This allows you to call private setters with an explicit receiver of the literal value self :
self.foo = bar
but not the dynamic value of self
baz = self baz.foo = bar
This still preserves the property that private method calls can be detected during parsing.
Two years ago, I filed an error stating that abbreviated assignment assignments do not work, that is:
self.foo += bar # NoMethodError
This error was fixed by re-expanding the rule for calling private methods (and now the rule is already becoming so complex that I am not going to write it down).
However, there are still many cases that are not covered by the existing rules, where methods simply cannot be called syntactically without an explicit receiver and, therefore, cannot be private:
self[foo] !self self + foo
and etc.
Some of them are fixed, some are not. The problem is that the rule has now become so complex that it is difficult to implement correctly. There were suggestions for changing the rule like this:
private methods can only be called without an explicit receiver or explicit receiver, which is a literal pseudo-variable self .
This is a good, simple, easy-to-understand rule that can be checked statically during parsing and does not have any of the difficult exceptions and corner cases that we currently have. However, it has not yet been implemented by AFAIK.