12

Folks I'll start by apologising as I'm sure this has been answered elsewhere - I just can't find an answer that explains it in a way I understand! I'm doing an MSc conversion course and there are some elementary basics that I'm still struggling with this, including this one - why making a variable private is better.

Say I have a Java class called Person, with a print method. I could create it and define it as such:

public class Person
{
    public String name;
    public String telephoneNumber;

    public void print()
    {
       System.out.println(name + " " + telephoneNumber);
    }
}

Then, in a main class, I could write the following code:

class testPerson
{
  public static void main(String[] args)
  {
    Person test;
    test = new Person();

    test.name = "Mary";
    test.telephoneNumber = "01234 567890";

    test.print();
  }
}

If I did this, the test.print(); would produce the output:

mary 01234 567890

However, I know this is considered poor coding. Variables should be private inside a public class, as we don't want to allow people to see how this information is stored or to be able to edit information without authorisation.

So now, I'll edit the Person class to declare the two Strings private and add get and set methods, like so:

private String name;
private String telephoneNumber;

public void setName (String name)
{
  this.name = name;
}

public void getName()
{
  return name;
}

// same code for telephone methods.

Now, in the main class, I would change the methods of setting name and telephone to the following:

mary.setName("Mary");
mary.settelephoneNumber("01234 567890");

According to the lecture notes I'm following, this is more efficient (although could be made even more efficient by adding in a Person() method to allow for instantiation etc.)

However, I'm struggling to see why this is better.
In the former method of doing things, the user could directly access the variables. But even though by hiding the variables they can't directly access them, the user can indirectly access and modify them which produces the exact same outcome.

Why is it that this is preferred and what no doubt silly thing am I missing/overlooking?

Andrew Martin
  • 5,619
  • 10
  • 54
  • 92
  • 3
    check out : http://programmers.stackexchange.com/questions/143736/why-do-we-need-private-variables questions pretty much covered there. – Mark Feb 04 '13 at 20:27
  • http://stackoverflow.com/questions/1568091/why-use-getters-and-setters may interest you. – Pshemo Feb 04 '13 at 20:30
  • 2
    Not sure if anyone will read this, but would the person who down-voted this question care to explain why? Thanks. – Andrew Martin Feb 04 '13 at 21:17
  • This is an old Qn but I seriously don't understand why was it closed as off-topic? This link came up first on my Google Search for something related to setting private variables. (The only downside of this Qn is its too verbose for what it is asking. That can be corrected by editing ) Marking it as duplicate is also fine but not off-topic. Re-opening it. – Pavan Manjunath Jan 19 '15 at 00:38
  • I consider this question much better formed than others, because it's in style "First I do A, but then I change it to B, so what's the difference?" with concrete examples. And this makes the issue much more understandable – Andrejs Feb 21 '16 at 15:59

5 Answers5

30

Pizza Delivery Analogy

  1. You order a Pizza for delivery.
  2. Pizza boy knocks the door and expects you to pay for it.
  3. You take out the money from your purse and hand it over to the delivery boy. (You are in control of hiding the internal details (drivers license etc.)) Alternatively,
    • You could hand over the purse to the delivery boy and ask him to take the money from it. By doing this you are no longer in control. You are exposing internal details.

Read about Information Hiding and Encapsulation is not information hiding.

Aravind Yarram
  • 78,777
  • 46
  • 231
  • 327
  • 1
    Only, JavaBeans as a standard **forces** you to hand over the wallet. The only technical difference is that you hand it over in a transparent ziplock bag. – Marko Topolnik Feb 04 '13 at 20:39
  • 1
    I'd extend the analogy to say not only are you giving him the wallet, you're not even telling him to take cash out of it - left to figure it out, he ends up taking a card payment, maxes out your account. Ok, maybe taking it a bit far, but the principle's there - you can't assume others will know what they can and can't touch inside your class! – MickMalone1983 Feb 05 '13 at 09:55
  • @Aravind but aren't you already allowing him to take as much as he wants using the setter? One can change the private variable to any value of their choice using the setter. So then what's the point? – Not Euler Jan 11 '20 at 16:57
14

It's not that it's more efficient, it's that it's more maintainable and a good practice.

For example, with setter methods, you could have your setTelephoneNumber actually check that the String is a valid telephone number before you actually do the setting. You couldn't possibly do that if you made the variable public. Using a setter from the very beginning means that you can go back and e.g. add validation later on, whereas if you had made the variable public, you would have to add a setter and modify all your users everywhere to use the setter instead of modifying the variable directly.

Louis Wasserman
  • 191,574
  • 25
  • 345
  • 413
  • 1
    Ah, never thought of that. That would make a lot of sense. So rather than using public variables and every time a user set some data checking it was legal, you could cover that all in one go by adding it to the setMethods. Never even considered that. Thanks – Andrew Martin Feb 04 '13 at 20:32
  • +1 You may not want a setter at all. Sometimes you might not want a getter, only a setter. – Peter Lawrey Feb 04 '13 at 20:36
  • I've voted for this as the answer as it was the first answer given and very clearly explained the benefits of private variables. Thanks! – Andrew Martin Feb 04 '13 at 20:47
  • and sometimes you want to return copy of object not the object itself. Getter will let you do that. – Tomasz Mularczyk Mar 17 '16 at 14:10
5

People will give you a million regurgitated reasons why it is better, but it is only better in some cases, not in all of them unequivocally. For example, take Java's own class GridBagConstraintsit has no methods at all (if you don't count clone, which it has anyway; all Java classes inherit it from Object). Why? Because there's a case where this is in fact more practical. And GridBagConstraints is a Java Bean in the purest sense: it's all about properties, no business logic there.

Let me report on another fact from practice: no setter ever validates its input; no getter ever calculates its result. In the world of JavaBeans, any such behavior will soon get in the way of the universal assumption that setters set, and getters get. Basically, if you diverge in any way from the exact equivalent of public fields, you lose.

The modern Java APIs, like Hibernate, acknowledge this fact by accepting naked public fields on an equal footing with JavaBean-style properties. Earlier versions didn't allow that, but as experience with Java accrues, the realization is finally dawning that public fields are OK.

Marko Topolnik
  • 195,646
  • 29
  • 319
  • 436
  • 3
    +1 Interesting answer, whilst access control is one of the most important facets of OOP it is important to realise that it's just a paradigm, a framework of good ideas rather than gospel. When you see some of the literally insane class inheritance chains people set up just to do 'proper' OO, you realise that it's not a perfect method! – MickMalone1983 Feb 04 '13 at 20:58
  • 1
    @MickMalone1983 Very well put. OOP is mostly considered not a means to an end, but an icon of religious perseverance. One should know when to leverage it, how to leverage it, and when to **avoid** it. – Marko Topolnik Feb 04 '13 at 21:07
2

You have to operate on the assumption that, at some point, someone else will use your code - and that someone else could be you, a year down the line. If you see a public property on a class, you should be able to assume that it's free for you to manipulate, if it's not to be directly modified you shouldn't be able to see it externally.

A good literal example would be the dimensions of a bitmap object. Most machines wouldn't like it if you tried to draw a bitmap of dimensions -10x-10, because such a thing would obviously be impossible to represent on a screen. If the width/height properties of this bitmap were simply public variables, it's possible they might be set to invalid values later on by a well-meaning coder (NEVER assume that it wouldn't happen), and when it came to render it - bang, you've got a frozen computer.

By hiding the variables and using a setter, you can prevent this ever happening:

private int _width = 10;

public void setWidth(int value)
{
     //Prevent the value moving into invalid range:

     if(value < 1)
          value = 1;

     if(value > 4096)
          value = 4096;

     //Now apply it
     _width = value;
}

However, for speed and convenience you don't have to develop your code like this at first - just make sure you go through it afterward and hide what you need to!

MickMalone1983
  • 1,054
  • 8
  • 17
0

there are also security issues to consider. a common example is a bank account. you have a balance, and you use deposit to put in money, and withdrawal to remove money. if balance was public, it could be modified without depositing or withdrawing money. that could be VERY bad.

within a method, you can put checks on things, such as making sure you don't take more money out of an account than actually exists. you can't really do that if you're accessing the values directly. it's about control.

Jeff Hawthorne
  • 568
  • 2
  • 12