86

I am currently working in Qt and so C++. I am having classes that has private data members and public member functions. I have public getters and setters for the data members available in the class.

Now my question is, if we have getters and setters for data members in our classes then what's the point in making those data members as private? I agree having private data members in Base classes sounds logical. But besides that, having private members and so do their getters and setters doesn't seem to be of a logical one for me.

Or instead can we make all variables as public so that no need for getters and setters at all? Is it a good practice to have those? I know having private members ensure data abstraction but having getters and setters actually lets access to those variables quite easily. Any pointers regarding this are welcome.

liaK
  • 11,422
  • 11
  • 48
  • 73
  • 1
    To control modification of a variable of one class in another class, By making the variable private we can control the way value gets modified , For example if in another class if the variable gets modified to negative using a setter we can throw an exception to not set to negative. In doing this the variable has to be turned into private , and to access that private variable we can use getter. – karthik gorijavolu Jan 11 '18 at 03:43

15 Answers15

85

Neither. You should have methods that do things. If one of those things happens to correspond with a specific internal variable that's great but there should be nothing that telegraphs this to the users of your class.

Private data is private so you can replace the implementation whenever you wish (and can do full rebuilds but that's a different issue). Once you let the Genie out of the bottle you will find it impossible to push it back in.

EDIT: Following a comment I made to another answer.

My point here is that you are asking the wrong question. There is no best practice with regard to using getters/setters or having public members. There is only what is best for your specific object and how it models some specific real world thing (or imaginary thing perhaps in the case of game).

Personally getters/setters are the lesser of two evils. Because once you start making getters/setters, people stop designing objects with a critical eye toward what data should be visible and what data should not. With public members it is even worse because the tendency becomes to make everything public.

Instead, examine what the object does and what it means for something to be that object. Then create methods that provide a natural interface into that object. It that natural interface involves exposing some internal properties using getters and setters so be it. But the important part is that you thought about it ahead of time and created the getters/setters for a design justified reason.

jmucchiello
  • 18,754
  • 7
  • 41
  • 61
  • 4
    Another useful difference: You can easily place a debugging breakpoint on a member function, but it's much harder to place a debugging breakpoint on a memory location for all instantiations of a class. This starts to lead to questions like: Do I need to know when this is changed or accessed? Are there any relationships between these data members that must be maintained? What are the multithreading safety requirements? – Jason Harrison Mar 21 '17 at 17:51
  • @JasonHarrison I see your point but you can always place a Watchpoint in most IDEs on a public variable to see when the value of that variable changes. – deepankardixit90 Feb 09 '21 at 11:14
41

No, it is not even remotely the same thing.

There are different levels of protection/implementation hiding that can be achieved by different approaches to a class interface:


1. Public data member:

  • provides both read and write (if not const) access to the data member
  • exposes the fact that data object physically exists and is physically a member of this class (allows one to create pointers of pointer-to-member type to that data member)
  • provides lvalue access to the data member (allows one to create ordinary pointers to the member)


2. A method that returns a reference to a piece of data (possibly to a private data member):

  • provides both read and write (if not const) access to the data
  • exposes the fact that data object physically exists but does not expose that it is physically a member of this class (does not allow one to create pointers of pointer-to-member type to the data)
  • provides lvalue access to the data (allows one to create ordinary pointers to it)


3. Getter and/or setter methods (possibly accessing a private data member):

  • provides both read and/or write access to the property
  • does not expose the fact that data object physically exists, let alone physically present in this class (does not allow one to create pointers of pointer-to-member type to that data, or any kind of pointers for that matter)
  • does not provide lvalue access to the data (does not allow one to create ordinary pointers to it)

The getter/setter approach does not even expose the fact that the property is implemented by a physical object. I.e. there might be no physical data member behind the getter/setter pair.

Taking above into the account, it is strange to see someone claim that a getter and setter pair is the same as a public data member. In fact, they have nothing in common.

Of course, there are variations of each approach. A getter method, for example, might return a const reference to the data, which would place it somewhere between (2) and (3).

AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765
  • 1
    @ AndreyT, really a good one... But is it a good practice having getters and setters for private members?? At least to those members who might be retrieved and modified so often... – liaK Jun 04 '10 at 19:36
  • 3
    They may not be the same, but they're used for the same purpose - providing public access to a property of an object. – Mark Ransom Jun 04 '10 at 19:37
  • 3
    You are looking at this form the C++ language point of view - my answer is from the application design perspective. –  Jun 04 '10 at 19:42
  • 1
    +1 for pointing out that a getter need not return a reference or pointer to the data. Being able to get a copy is a lot different than being able to get the lvalue. – tloach Jun 04 '10 at 19:47
  • 1
    @liaK - It has nothing to do with what is good practice and everything to do with what does your object model. See my answer above. You are asking the wrong question. – jmucchiello Jun 04 '10 at 20:10
26

If you have getters and setters for each of your data items, there is no point in making the data private. That's why having getters and setters for each of your data items is a bad idea. Consider the std::string class - it (probably) has ONE getter, the size() function, and no setters at all.

Or consider a BankAccount object - should we have SetBalance() setter to change the current balance? No, most banks won't thank you for implementing such a thing. Instead, we want something like ApplyTransaction( Transaction & tx ).

  • 1
    you mean to say that we should avoid having getters and setters for the data members? – liaK Jun 04 '10 at 19:12
  • +1 for each of the answer and the comment. It is hard to have an invariant defined for a class if everything is effectively public. If there is no invariant there really is no class. – Amardeep AC9MF Jun 04 '10 at 19:16
  • 2
    +1 you want to have an interface by "task"/"operation", not getters/setters or public data. – Mark B Jun 04 '10 at 19:20
  • 3
    Neil, I think that's not a good suggestion. Getters and setters are CRUCIAL to Qt's property system. You can't have properties without them. Also, getters and setters can do other necessary stuff, like lock a mutex, query a database, implicit sharing, reference counting, lazy loading and so on. – CMircea Jun 04 '10 at 19:26
  • @iconiK Although the OP mentioned Qt, the question is not tagged as such. Personally, I'm quite anti properties (and I'm an ex Delphi programmer, so I know whereof I speak), particularly in the business model, but they are also difficult (sometimes impossible) to implement in GUIs where you have several related properties with constraints on all of them. –  Jun 04 '10 at 19:30
  • 3
    Your first sentence kind of threw me off. There *is* still a point in making the data private even if you have getters and setters for it. That seems orthogonal to your larger point, that it's okay (even desirable) to have private data *without* getters and setters. – Bill the Lizard Jun 04 '10 at 19:32
  • 2
    @Bill You are right - exaggeration for effect there. My point is the general badness of get/set functions. –  Jun 04 '10 at 19:37
  • Setters/Getters do have some purpose. For example, in C++0x, if you had a public variable, you could call std::move on it. I guess there are ways to do this anyway, but it helps. It also protects users from implementation change. I wouldn't use them in systems that are finished development, only during development to make code more re-usable. – Puppy Jun 04 '10 at 20:44
14

Make the data public. In the (rather unlikely) event that you do someday need logic in the "getter" or "setter", you can change the data type to a proxy class that overloads operator= and/or operator T (where T=whatever type you're using now) to implement the necessary logic.

Edit: the idea that controlling access to the data constitutes encapsulation is basically false. Encapsulation is about hiding the details of the implementation (in general!) not controlling access to data.

Encapsulation is complementary to abstraction: abstraction deals with the object's externally visible behavior, while encapsulation deals with hiding the details of how that behavior is implemented.

Using a getter or setter actually reduces the level of abstraction and exposes the implementation -- it requires client code to be aware that this particular class implements what is logically "data" as a pair of functions (the getter and setter). Using a proxy as I've suggested above provides real encapsulation -- except for one obscure corner case, it completely hides the fact that what is logically a piece of data is actually implemented via a pair of functions.

Of course, this needs to be kept in context: for some classes, "data" isn't a good abstraction at all. Generally speaking, if you can provide higher level operations instead of data, that's preferable. Nonetheless, there are classes for which the most usable abstraction is reading and writing data -- and when that's the case, the (abstracted) data should be made visible just like any other data. The fact that getting or setting the value may involve more than simple copying of bits is an implementation detail that should be hidden from the user.

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
  • 1
    "Rather unlikely"? How do you know? There are many reasons logic may be added in the future - logging, thread safety, validation, etc. – Rob Jun 04 '10 at 19:23
  • 2
    "you can change the data type to a proxy class" - yes you can, but it's a band-aid that is likely to be more trouble than it's worth. – Mark Ransom Jun 04 '10 at 19:23
  • 3
    Whether or not getters/setters are good design, "there is a hackish workaround" is not an argument, it's an excuse. – BlueRaja - Danny Pflughoeft Jun 04 '10 at 19:29
  • 4
    @BlueRaja: Nonsense. See the edit. The fact is, either the data should be entirely invisible (not public, and no getter or setter either) or else it should be visible **as data**, in which case a getter and setter are exposing the wrong abstraction. – Jerry Coffin Jun 04 '10 at 19:37
  • 3
    @Rob: Simple statistics -- even in code that's been maintained for *decades*, the vast majority of getters/setters remain nothing but simple pass-throughs that aren't accomplishing anything useful at all. – Jerry Coffin Jun 04 '10 at 19:38
  • 1
    @Mark: Providing the right abstraction is *not* a band-aid; it's the right thing to do. That's well worthwhile. – Jerry Coffin Jun 04 '10 at 19:39
  • If I have 2 member variables of the same type your hack doesn't work. I much prefer to have a setter in the form void variablename (variabletype) and a getter in the form variabletype variablename() if I absolutely need to have both a getter and a setter for a class member. – tloach Jun 04 '10 at 19:43
  • 2
    @tloach: You clearly don't understand what's being advocated. Having two (or a dozen) member variables of the same type doesn't prevent it from working, and doesn't even cause the slightest problem. – Jerry Coffin Jun 04 '10 at 19:47
  • 1
    Whether you agree with what he's saying or not, this is an extremely well argued point. – Dennis Zickefoose Jun 04 '10 at 22:05
  • 5
    @Jerry is right. Either make the data public, or make the class abstract and move the data to a subclass. the middle ground - private data w/public getters & setters - is the hack. – John Dibling Nov 26 '10 at 17:35
  • 1
    I'm starting to use something like this. To me, the most flexible approach is for classes to have most data private, but some public, as long as that public data is a class. I generally avoid `getX()` and `setX()` functions, preferring higher-level traits of the class, even if that happens to be implemented as just returning a variable. However, if I want read / write access for all, but there are certain constraints on that value, then my `setX` member function verifies that the constraints are met and throws if they aren't. If I get more complex than that, a new, public class seems better. – David Stone May 08 '12 at 23:10
12

Getters and Setters let you apply logic to the input/output from the private members therefore controlling access to the data (Encapsulation to those who know their OO terms).

Public variables leave your class' data open to the public for uncontrolled and non-validated manipulation which is almost always un-desirable.

You have to think about these things long term as well. You may not have validation now (which is why public variables seem to be a good idea) but there's a chance they'll be added down the road. Adding them ahead of time leaves the framework so there's less re-factoring down the raod not to mention the validation won't break dependent code this way).

Keep in mind, though, that doesn't mean Each and Every private variable needs its own getter/setter. Neil brings up a good point in his banking example that sometimes Getters/Setters just don't make sense.

Justin Niessner
  • 242,243
  • 40
  • 408
  • 536
5

If you are quite sure your logic is simple, and you never need to do something else when reading/writing a variable, it's better to keep the data public. In C++ case, I prefer to use struct instead of class to emphasize the fact that the data is public.

However, quite often you need to do some other things when accessing data members, or you want to give yourself freedom to add this logic later. In this case, getters and setters are good idea. Your change will be transparent to the clients of your code.

A simple example of additional functionality - you may want log a debug string every time you access a variable.

Igor Krivokon
  • 10,145
  • 1
  • 37
  • 41
5

Aside from the encapsulation concerns (which are reason enough), it is very easy to set a breakpoint whenever the variable is set/accessed when you have getters/setters.

BlueRaja - Danny Pflughoeft
  • 84,206
  • 33
  • 197
  • 283
4

Reasons to use public fields rather than getters and setters include:

  1. There are no illegal values.
  2. The client is expected to edit it.
  3. To be able to write things such as object.X.Y = Z.
  4. To making a strong promise that the value is just a value and there are no side-effects associated with it (and won't be in the future either).

Depending on what sort of software you work on, these might all be really exceptional cases (and if you think you've come across one you're probably wrong) or they might occur all the time. It really depends.

(From Ten Questions on Value-Based Programming.)

Ian Goldby
  • 5,609
  • 1
  • 45
  • 81
3

On a strictly practical basis, I'd suggest you start by making all of your data members private, AND make their getters and setters private. As you find out what the rest of the world (i.e., your "(l)user community") actually needs, you can expose the appropriate getters and/or setters, or write appropriately-controlled public accessors.

Also (for Neil's benefit), during debugging time, it is sometimes useful to have a convenient place to hang debug prints, and other actions, when a particular data member is read or written. With getters and setters, this is easy. With public data members, it is a huge pain in the posterior.

John R. Strohm
  • 7,547
  • 2
  • 28
  • 33
3

I believe that using getters and setters simply for getting and setting the value is useless. There is no difference between a public member and private one with such methods. Use getters and setters only when you need to control the values somehow or when you think that it might be useful in the future (adding some logic won't make you edit the rest of the code).

As a reference, read C++ guidelines (C.131)

Hitokage
  • 733
  • 8
  • 19
2

I've always thought that getters and setters are deliberately verbose in most programming languages specifically to make you think twice about using them - why does your caller need to know about the inner workings of your class should be the question at the front of your mind.

blissapp
  • 1,330
  • 12
  • 19
1

I suggest that you don't have public data members (except for POD structs). I also don't recommend that you have getters and setters for all of your data members. Rather, define a clean public interface for your class. This may include methods that get and/or set property values, and those properties may be implemented as member variables. But don't make getters and setters for all of your members.

The idea is that you separate your interface from your implementation, allowing you to modify the implementation without the users of the class having to change their code. If you expose everything through getters and setters, you've not improved anything over using public data.

Fred Larson
  • 60,987
  • 18
  • 112
  • 174
  • PODS (structs) represent a significant exception to the "no public data members" rule; it's too bad Microsoft didn't make an exception for them in the design of some .net value types. Read/write struct properties in .net have weird quirky behaviors which exposed struct fields do not. – supercat Nov 28 '12 at 20:21
1

Using getters and setters will allow you to modify the way that you give the values to the user.

Consider the following:

double premium;
double tax;

You then write code all over the place using this premium value to get the premium:

double myPremium = class.premium;

Your specs just changed and premium from the user's standpoint needs to be premium + tax

You will have to modify everywhere that that premium value is being used in your code, and add tax to it.

If instead you implemented it as such:

double premium;
double tax;

double GetPremium(){return premium;};

All of your code would be using GetPremium() and your tax change would be one line:

double premium;
double tax;

double GetPremium(){return premium + tax;};
Ben Burnett
  • 1,554
  • 10
  • 17
  • 1
    And then when you need the premium without the tax what do you call the new getter? Instead create a method to calculate something real world on your object and let it decide if its going to combine premium and tax. – jmucchiello Jun 04 '10 at 20:19
  • Yes, I suppose my example is not a true getter/setter. I was simply trying to illustrate that getters and setters let you write the implementation independent of what goes on behind the hood. I suppose a better example would be if the variable premium changed to m_dPremium or something. – Ben Burnett Jun 04 '10 at 20:41
0

Getters and Setters exist primarily so that we can control how members are fetched, and how they are set. Getters and setters dont exist only as a way to access a specific member, but to ensure that before we try and set a member, that it perhaps meets certain conditions, or if we fetch it, we could control that we return a copy of that member in the case of a non-primitive type. Overall, you should try and use g/s'ers when you want to pipeline how a data member is to be interacted with, without them would cause the member is be used in an adhoc fashion.

0

The return value also effects the use of getters and setters. It's a difference to get the value of a variable or to get access to private data member variable. By-value keeps integrity, by-reference or by-pointer not so much.

DaClown
  • 4,171
  • 6
  • 31
  • 31