Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should I use public or private variables?

I am doing a large project for the first time. I have lots of classes and some of them have public variables, some have private variables with setter and getter methods and same have both types.

I decided to rewrite this code to use primarily only one type. But I don't know which I should use (variables which are used only for methods in the same object are always private and are not subject of this question).

I know the theory what public and private means, but what is used in the real world and why?

like image 327
Marek Čačko Avatar asked Jan 18 '13 13:01

Marek Čačko


People also ask

Should variables be private or public?

Private member variables are preferred over public member variables, mainly for the reasons stated above (encapsulation, well-specified data, etc..).

When should you use private variables?

Making a variable private "protects" its value when the code runs. At this level, we are not concerned with protecting it from other programmers changing the code itself. The point of so-called "data hiding" is to keep internal data hidden from other classes which use the class.

When Should a variable be public?

You can use public variables as a shortcut to avoid the need to provide getters and setters, but there is no need to do so, and because there is a negative consequence (increased coupling to the internal design of the class) I would suggest that sacrificing design for brevity in this way is not often a good idea.

Should class variables be public?

7.1. Considerations Regarding Access RightsNever specify public or protected member data in a class. The use of public variables is discouraged for the following reasons: A public variable represents a violation of one of the basic principles of object-oriented programming, namely, encapsulation of data.


2 Answers

private data members are generally considered good because they provide encapsulation.

Providing getters and setters for them breaks that encapsulation, but it's still better than public data members because there's only once access point to that data.

You'll notice this during debugging. If it's private, you know you can only modify the variable inside the class. If it's public, you'll have to search the whole code-base for where it might be modified.

As much as possible, ban getters/setters and make properties private. This follows the principle of information hiding - you shouldn't care about what properties a class has. It should be self-contained. Of course, in practice this isn't feasible, and if it is, a design that follows this will be more cluttered and harder to maintain than one that doesn't.

This is of course a rule of thumb - for example, I'd just use a struct (equivalent with a class with public access) for, say, a simple point class:

struct Point2D {    double x;    double y; }; 
like image 89
Luchian Grigore Avatar answered Sep 21 '22 10:09

Luchian Grigore


Since you say that you know the theory, and other answers have dug into the meaning of public/private, getters and setters, I'd like to focus myself on the why of using accessors instead of creating public attributes (member data in C++).

Imagine that you have a class Truck in a logistic project:

class Truck { public:     double capacity;      // lots of more things... }; 

Provided you are northamerican, you'll probably use gallons in order to represent the capacity of your trucks. Imagine that your project is finished, it works perfectly, though many direct uses of Truck::capacity are done. Actually, your project becomes a success, so some european firm asks you to adapt your project to them; unfortunately, the project should use the metric system now, so litres instead of gallons should be employed for capacity.

Now, this could be a mess. Of course, one possibility would be to prepare a codebase only for North America, and a codebase only for Europe. But this means that bug fixes should be applied in two different code sources, and that is decided to be unfeasible.

The solution is to create a configuration possibility in your project. The user should be able to set gallons or litres, instead of that being a fixed, hardwired choice of gallons.

With the approach seen above, this will mean a lot of work, you will have to track down all uses of Truck::capacity, and decide what to do with them. This will probably mean to modify files along the whole codebase. Let's suppose, as an alternative, that you decided a more theoretic approach.

class Truck { public:     double getCapacity() const         { return capacity; }      // lots of more things... private:     double capacity; }; 

A possible, alternative change involves no modification to the interface of the class:

class Truck { public:     double getCapacity() const         { if ( Configuration::Measure == Gallons ) {             return capacity;           } else {              return ( capacity * 3.78 );           }         }       // lots of more things... private:     double capacity; }; 

(Please take int account that there are lots of ways for doing this, that one is only one possibility, and this is only an example)

You'll have to create the global utility class configuration (but you had to do it anyway), and add an include in truck.h for configuration.h, but these are all local changes, the remaining of your codebase stays unchanged, thus avoiding potential bugs.

Finally, you also state that you are working now in a big project, which I think it is the kind of field in which these reasons actually make more sense. Remember that the objective to keep in mind while working in large projects is to create maintainable code, i.e., code that you can correct and extend with new functionalities. You can forget about getters and setters in personal, small projects, though I'd try to make myself used to them.

Hope this helps.

like image 43
Baltasarq Avatar answered Sep 22 '22 10:09

Baltasarq