Java – Why do we have mutator methods

javalanguage-agnosticobject-orientedpython

I'm switching from Java to Python and am having trouble understanding the @Property decorator. I realized in OOP languages (such as Java) I don't fully understand the point of mutator methods in the following sense:

Say we have a private variable x. So we need to make a mutator method

public void setX(int val) {
  x = val;
}

Now if x had been public then we could have just did x = val and it would have been easier and there would have been no difference. Now in a more complicated scenario, we could add restrictions, perhaps it doesn't make sense for x to be less than 10

public void setX(int val) {
  if(x < 10)
    x = 10;
  else
    x = val;
}

So in a sense is the point of having mutator methods to impose restrictions on the data? So it's to achieve encapsulation? I'm thinking of this because with Python's @Property (correct me if I'm wrong) you're not calling a mutator method but in effect it works the same way in the sense additional logic can happen before the value is changed.

A corolary question is, if we do have such a simple mutator method as in the first example, should the variable just be made public?

Best Answer

To answer your last question first - in Java you should always use accessor and mutator methods, because if you make a public field and later decide it needs extra logic - you're gonna have a bad time. If you are lucky and your code is not a library "all" it'll take is cleaning the build product, rebuilding, and going through countless places where you access that variable, changing them by hand. If you are a library - though luck. You're gonna break your users code...

In Python - it doesn't matter. Attribute syntax(and AFAIK implementation) is the same for fields and properties. The only difference is whether your custom method will be called or the default __getattribute__/__setattribute__ which will look inside the __dict__(or set a value in it). So if you don't need the extra logic - just use a regular field. You can always change it later.

As for the "why" - the most common reason for using a @property in Python is that you don't store the actual , direct value inside the object.

For example:

class Vector2D(object):
    def __init__(self, x, y):
        self.x = x
        self.y = y

    @property
    def length(self):
        return (self.x ** 2 + self.y ** 2) ** 0.5

    @length.setter
    def length(self, value):
        multiplier = value / self.length
        self.x *= multiplier
        self.y *= multiplier

We don't store the length directly - we only store x and y. But we can still get and set the length like it was an ordinary property - and our @property code does the work behind the scenes for us.