Here's an interesting case I can't seem to explain. It looks like private setters are 'kind of' private, but sometimes there are exceptions to that. Regular private methods seem to behave differently to private setters:
class TestClass
def do
self.foo = :bar # fine
self.baz # error
end
private
def foo=(other)
@foo = other
end
def baz
end
end
TestClass.new.do
The above code sets @foo
just fine, despite being called on an explicit self
. Then it fails to call #baz
, because #baz
is a private method.
What's up with this?
Usually you want setters/getters to be public, because that's what they are for: giving access to data, you don't want to give others direct access to because you don't want them to mess with your implementation dependent details - that's what encapsulation is about.
The reason for declaring the getters and setters private is to make the corresponding part of the object's abstract state (i.e. the values) private. That's largely independent of the decision to use getters and setters or not to hide the implementation types, prevent direct access, etc.
Private setters force you to set values inside of constructor or later.
No outside class can access private data member (variable) of other class. However if we setup public getter and setter methods to update (for example void setSSN(int ssn) )and read (for example int getSSN() ) the private data fields then the outside class can access those private data fields via public methods.
Private setters are special because otherwise they couldn't be called at all:
foo = :bar
Assigns to the local variable foo
, it doesn't send the message foo=
.
Note that setters aren't the only things which cannot be called without an explicit receiver. +@
, -@
, !
, ~
, []
, []=
, +
, -
, *
, /
, %
, &
, |
, ^
, **
, <<
, >>
, ==
, ===
, =~
, !~
, !=
, <
, >
, <=
, >=
, <=>
and probably some others I forgot also cannot be called without an explicit receiver. And then there's stuff like +=
, <<=
and so on.
There need to be exceptions for all of those. Unfortunately, there are only exceptions for some of those.
It has been proposed to change the rules for private
from
Can only be called without an explicit receiver, except for [this long list of exceptions which is really complicated, and still not complete].
to
Can only be called without an explicit receiver or the literal special variable
self
as receiver.
which preserves all the current properties of the definition (the most important one being that it can be determined statically at parse time).
But so far, nothing has come of it.
If you don't use self
when using the setter method, it will instead assign the value to a local variable. More details.
In the code below, I've removed self
from the assignment to foo, and you can see the the setter is not being used b/c @foo
is nil
:
def do
foo = :bar # fine
baz # error
puts @foo # prints nil
puts foo # prints 'bar'
end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With