views:

732

answers:

14

Hi All,

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.

+9  A: 

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
+15  A: 

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 ).

anon
you mean to say that we should avoid having getters and setters for the data members?
liaK
@liaK Yes, I do.
anon
+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
+1 you want to have an interface by "task"/"operation", not getters/setters or public data.
Mark B
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.
iconiK
@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.
anon
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
@Bill You are right - exaggeration for effect there. My point is the general badness of get/set functions.
anon
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.
DeadMG
+2  A: 

If you make your variables public then later decide that you need to do some small amount of processing, like validating inputs before a value is changed, you'll have to go back and change all the code that sets those values directly. Use simple setters and getters from the beginning and you're free to change your class without changing its clients.

Bill the Lizard
This is simply false. See my answer for an alternative.
Jerry Coffin
@Jerry: "Simply false" is putting it kind of strongly. Maybe you don't *have* to change the client code, but I still find the getter/setter approach much simpler.
Bill the Lizard
@Bill:you may find it simpler, but "you'll have to go back and change all the code..." is exactly what I said: simply false.
Jerry Coffin
A: 

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
"Rather unlikely"? How do you know? There are many reasons logic may be added in the future - logging, thread safety, validation, etc.
Rob
"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
Whether or not getters/setters are good design, "there is a hackish workaround" is not an argument, it's an excuse.
BlueRaja - Danny Pflughoeft
@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
@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
@Mark: Providing the right abstraction is *not* a band-aid; it's the right thing to do. That's well worthwhile.
Jerry Coffin
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
@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
Whether you agree with what he's saying or not, this is an extremely well argued point.
Dennis Zickefoose
+21  A: 

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
I'd +2 if i could !
Benoît
+1  A: 

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
A: 

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
+2  A: 

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
I find private get/set functions quite useful during development, even when they have no business in the public interface.
Dennis Zickefoose
+2  A: 

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
+1 for using struct instead.
Rob
+2  A: 

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
+2  A: 

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
+8  A: 

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 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).

AndreyT
@ 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
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
You are looking at this form the C++ language point of view - my answer is from the application design perspective.
anon
+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
@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
@jmucchiello - yep... gotta a picture now.. thnx a lot..
liaK
+1  A: 

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
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
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
A: 

Hi liak,

I am very beginner in Qt. I want to develop a network chat system using Qt. An example is given with Qt. but it has some problem. It stored all client's messages in a same TextEdit.I want as like yahoo messenger where we can chat privately using pop-up window for each clients. Please give me some resources with details example.

kernel.roy
Ask this as a separate question, with what you want to achieve, how far you achieved, some code that gives the problem, etc., so that everyone can help you.. You can ask a question by clicking **Ask Question** at the right top of your profile page..
liaK