27

I have a class with a variable that is private and the class has a getter and a setter for that variable. Why not make that variable public?

The only case I think you have to use getters and setters is if you need to do some operation besides the set or the get. Example:

void my_class::set_variable(int x){
   /* Some operation like updating a log */
   this->variable = x;
}
8
  • 10
    Getters and setters are there for shielding. Someday you might want to do this->variable = x + 5, or call a UpdateStatistics function in setter, and in those cases classinstancea->variable = 5 will cause problems.
    – Coder
    Jul 31, 2011 at 22:01
  • 1
    Another example is: set_inch, set_centimeter, get_inch, get_centimeter, with some spooky actions.
    – rwong
    Jul 31, 2011 at 22:49
  • Yep, getters and setters help you control your instance variables the way in which you desire them to be controlled.
    – j1199dm
    Aug 1, 2011 at 1:43
  • 7
    @Coder: you can always add your getter/setter when that need arises? Or is this something you cannot easily do in C++ (my experience is mostly Delphi)? Aug 1, 2011 at 5:53
  • This question: programmers.stackexchange.com/questions/21802/… may be of interest. Aug 1, 2011 at 6:47

7 Answers 7

23

Have you ever heard about a property?

A property is a field that has "built-in" accessors (getters and setters). Java, for instance, doesn't have properties, but it's recommended to write the getters and setters to a private field. C# has properties.

So, why do we need getters and setters? Basically we need it to protect/shield the field. For instance, you're not accessing the field in memory reference, you're accessing a method that will then change the field (reference). That method is able to perform some operations that a user is not willing to know (encapsulating behavior), like in your example. Imagine, for instance, that a dozen classes use your public field and you need to change the way it's used... You would have to look at each of those classes in order to change the way they are using the field... Not so "OOlysh".

But, for instance, If you have a boolean field called dead. You should think twice before declaring a setDead and isDead. You should write accessors that are human readable, for instance, kill() instead of setDead.

However, there are a lot of frameworks that assume that you are following the JavaBean naming convention (talking about Java here), therefore, in those cases, you should declare all the getters and setters following the naming convetion.

9
  • 2
    Now "human readable" is finally an argument that I can "grok." All other arguments I usually hear are some sort of future proofing that are just as easily addressed when the need arises... Aug 1, 2011 at 5:55
  • 15
    Your disdain for "future proofing" is common, but misguided. Yes, you can address such changes when the need arises, if you are the only client of that code. If you never publish your solution for external clients, you can simply incur technical debt and no one need ever know. But internal projects have a habit of becoming public when you least expect it, and then woe be unto you. Aug 1, 2011 at 6:09
  • 2
    You actually raise a fantastic point. kill is not a set/get, it's an action. It completely hides the implementation--it's how you code OO. Properties, on the other hand, just as stupid as setters/getters--stupider even because the easy syntax encourages people to just add them to variables when they aren't even needed (OO-Furbar waiting to happen). Who would think to use kill() when they could just add a "property" tag to their dead flag?
    – Bill K
    Aug 2, 2011 at 3:24
  • 1
    The question is tagged a C++ question. C++ doesn't support properties, so why would you even post this? Sep 26, 2012 at 19:53
  • 1
    @ThomasEding: C++ is somewhat unique in having overridable assignment operators. While C++ doesn't use the term "property" the same way as languages like C# or VB.NET, the concept is still there. It is possible in C++ to use operator overloading so that foo.bar = biz.baz+5 will call a function on biz to evaluate baz, then add five to it and call a function on foo to set bar to the resulting value. Such overloads aren't called "properties", but they can serve the same purpose.
    – supercat
    Jul 11, 2015 at 16:12
31

This is not the most popular opinion but I don't see much of a difference.

Setters and getters are a fairly bad idea. I've thought about it and honestly I can't come up with a difference between a setter/getter a property and a public variable in practice.

In THEORY a setter and getter or property add a place to take some extra actions when a variable is set/gotten and in theory they isolate your code from changes.

In reality I rarely see setters and getters used to add an action, and when you do want to add an action you want to add it to ALL the setters or getters of a class (like logging) which should make you think that there ought to be a better solution.

As for isolating design decisions, if you change an int to a long you still have to change your setters and at least check every line that accesses them by hand--not much isolation there.

Mutable classes should be avoided by default anyway, so adding a setter should be a last resort. This is mitigated with the builder pattern where a value can be set until the object is in a desired state then the class can become immutable and your setters will throw exceptions.

As for getters--I still can't come up with much of a difference between a getter and a public final variable. The problem here is that it's bad OO in either case. You shouldn't be asking for a value from an object and operating on it — you should be asking an object to do an operation for you.

By the way, I'm in no way advocating public variables--I'm saying setters and getters (and even properties) are way too close to already being public variables.

The big problem is simply that people who aren't OO programmers are too tempted to use setters and getters to make objects into property-balls (structures) that are passed around and operated on, pretty much the opposite of how Object Oriented code works.

10
  • One good thing apart from other answers here, about getter setter is: I can add some validations/conversions inside it befor the actual private variable assumes it's value.
    – WinW
    Aug 1, 2011 at 7:22
  • 1
    @Kiran true, but if you set it in the constructor you can have validations AND you have an immutable class. For setters I'm not saying a public writable variable is good, I'm saying that even setters are bad. For getters I might consider a public final variable a viable alternative.
    – Bill K
    Aug 2, 2011 at 3:12
  • In some languages like C#, properties are not binary-compatible with public variables, so if you make a public variable part of your API, but then want to add some validation, you're going to break your client's program when you convert it to a property. Better to make it a public property from the start. Sep 26, 2012 at 19:44
  • @RobertHarvey That still means you are exposing properties. My entire point was that exposing properties should be avoided, and when necessary you should try to restrict them to getters and make your class immutable. If your class is immutable why would you need code in a getter--and therefore it follows that you might as well not have a getter. If you are incapible of writeing a class without exposed mutable properties then yes, a setter is always better than a writable public variable (and getting shot in the foot is always better than being stabbed in the gut).
    – Bill K
    Apr 25, 2013 at 16:45
  • 1
    Mutable state is acceptable, but again you should ask your object to do something for you, not do somethign to your object--therefore when you mutate your state a setter is not a great way to do it, try writing a business method with logic in it instead. For instance, "move(Up5) rather than setZLocation(getZLocation()+5)".
    – Bill K
    Apr 25, 2013 at 16:53
8

The user of getters and setters goes into the principle of encapsulation. This will allow you to change how things work inside of the class and keeping everything functioning.

For instance if 3 other objects call foo.bar to get the value of bar and you decide to change the name of bar to far you have a problem on your hands. If the objects called foo.bar you would have to change all the classes that have this. If a setter/getter is used then you have nothing to change. Another possibility is changing the type of the variable in which case just add some transformation code to the getter/setter and you are fine.

7
  • 1
    +1 - the member variable is implementation, the getter and setter are interface. Only the interface should be public. Also, the getter and setter names should make sense in terms of an abstraction, irrespective of whether there is a simple member variable underlying them or some other implementation. There are exceptions - cases where a subsystem built from tightly-coupled classes is the easiest way - but that just pushes the data-hiding boundary up a level anyway, to the class that represents the whole subsystem.
    – user8709
    Jul 31, 2011 at 22:27
  • Couldn't I simply introduce the getter and/or setter when I need to change the work inside of the class? It is something that is easily done in Delphi, but perhaps not in other languages? Aug 1, 2011 at 5:57
  • @ marjan Sure, you could introduce the getter/setter at any point later on. The issue then is that you have to go back and change ALL the code that was using the public field instead of getter/setter. I'm not sure if I'm the one who is confused or you are. 0.o
    – Pete
    Aug 1, 2011 at 6:14
  • 3
    Personally, I think this is a bit of a bogus argument. If you change the meaning of a variable but the variable has a getter and setter, then it doesn't matter what it is called. It's not a visible part of the interface. You are much more likely to want to change the name of the getters and setters themselves to indicate to clients the change or clarification of the meaning of the encapsulated variable. In this latter case, you are in no better position that with a public variable. This is quite aside from the argument that a variable with getters and setters is more exposed than encapsulated.
    – CB Bailey
    Aug 1, 2011 at 9:04
  • 1
    A refactor operation is virtually free either way, so I don't really buy this one. Plus it's Very Bad Form to use a setter or getter unless you absolutely need it--eventually you'll get people who don't understand the concept just automatically adding setters and getters for members instead of when they are needed which is just dripping seeds of evil throughout your codebase.
    – Bill K
    Aug 2, 2011 at 3:15
5

Using getters and setters also enables you to control what content gets stored in a particular variable. If the content needs to be of a certain type or value, part of your setter code can be to ensure that the new value meets these requirements. If the variable is public you can't ensure these requirements are met.

This approach also makes your code more adaptable and manageable. Its much easier to make changes to the architecture of a class if you have functions in place that keep that architecture hidden from all other classes or functions that utilize that class. The already mentioned change of a variable name is only one of many many changes that are much easier to make if you have functions like getters and setters. The overall idea is to keep as much private as possible, especially your class variables.

3
  • Thanks a lot! I was thinking the same case you mention. If I want a variable to be content in [0,1] I should check the incoming value in its setter :)
    – Oni
    Jul 31, 2011 at 22:17
  • When you are the only developer working on a project it is easy to think that things like this are useless but when you find yourself working with a team you will find that being in the habit of techniques like this will come in very handy and help you avoid a lot of bugs down the road.
    – Kenneth
    Aug 1, 2011 at 0:27
  • If you are using C#, use properties, you can use a property to set a private instance if needed based on some logic in the setter part of the property.
    – j1199dm
    Aug 1, 2011 at 1:41
2

You say "The only case I think you have to use getters and setters is if you need to do some operation besides the set or the get. ".

You should use getters and setters if at some point in the future you might need to do some operation besides the set and get and you don't want to change thousands of lines of source code when that happens.

You should use getters and setters if you don't want someone to take the address of the variable and pass it around, with disastrous consequences if that variable can then be changed without any source code mentioning it, or even after the object stopped existing anymore.

1
  • Your last paragraph makes an excellent point which cuts both ways: requiring the use of getters and setters will prevent other code from taking the address of something. In cases where there would be significant benefits and few downsides to having outside code take the addresses of things, such restriction could be a bad thing. if there would be few benefits and severe downsides to allowing such behavior, restricting it could be a good thing.
    – supercat
    Jul 11, 2015 at 16:14
1

First off lets be clear on the paradigm.

  • Data Structures -> a layout of memory that can be traversed and manipulated by suitably knowledgeable functions.
  • Objects -> a self contained module that hides its implementation and provides an interface that may be communicated through.

Where is a getter/setter useful?

Are getters/Setters useful in Data Structures? No.

A Data Structure is a memory layout specification that is common to and manipulated by a family of functions.

Generally any old new function can come along and manipulate a data-structure, if it does so in a way that the other functions can still understand it, then the function joins the family. Otherwise its a rogue function and a source of bugs.

Don't get me wrong there could be several families of functions warring over that data-structure with snitches, turn-coats, and double-agents everywhere. Its fine when they each have their own data-structure to play with, but when they share it... just imagine several crime families disagreeing over politics, it can become a mess really fast.

Given the mess extended function families can achieve, is there a way to encode the data structure so that rogue functions don't mess everything up? Yes, they are called Objects.

Are getters/setters useful in Objects? No.

The whole point of wrapping a data structure up in an object was to ensure that no rogue functions could exist. If the function wanted to join the family, it had to be thoroughly vetted first and then become part of the object.

The point/purpose of a getter and a setter is to allow functions outside of the object to alter the memory layout of the object directly. That sounds like an open door to permit in rogues...

The Edge Case

There are two situations were a public getter/setter make sense.

  • A portion of the data-structure within the object is managed by the object, but not controlled by the object.
  • An interface describing a high-level abstraction of a data-structure where some elements are expected to not be in control of the implementing object.

Containers and container interfaces are perfect examples of both of these two situations. The container manages the data-structures (linked-list, map, tree) internally but hands control over the specific element to all and sundry. The interface abstracts this and ignores the implementation entirely and describes just the expectations.

Unfortunately many implementations get this wrong and define the interface of these sorts of objects to give direct access to the actual object. Something like:

interface Container<T>
{
    typedef ...T... TRef; //<somehow make TRef to be a reference or pointer to the memory location of T
    TRef item(int index); 
}

This is broken. The implementations of Container must explicitly hand control of their internals over to whomever uses them. I've yet to see a mutable-value language where this is fine (languages with immutable-value semantics are by definition fine from a data-corruption perspective, but not necessarily from a data-spying perspective).

You can improve/correct the getters/setter by using only copy-semantics, or by using a proxy:

interface Proxy<T>
{
     operator T(); //<returns a copy
     ... operator ->(); //<permits a function call to be forwarded to an element
     Proxy<T> operator=(T); //< permits the specific element to be replaced/assigned by another T.
}

interface Container<T>
{
     Proxy<T> item(int index);
     T item(int index); //<When T is a copy of the original value.
     void item(int index, T new_value); //<where new_value is used to replace the old value
}

Arguably a rogue function could still play mayhem here (with enough effort most things are possible), but the copy-semantics and/or proxy reduces the chance for a number of errors.

  • overflow
  • underflow
  • interactions with the sub element are type-checked/type-checkable (in type lose languages this is a boon)
  • The actual element may or may not be memory resident.

Private Getters/Setters

This is the last bastion of getters and setters working on the type directly. In fact I wouldn't even call these getters and setters but accessors and manipulators.

In this context sometimes manipulating a specific portion of the data-structure always/almost-always/generally requires specific book keeping to occur. Say when you update the root of a tree the look-aside cache needs to be purged, or when you access the external data element, a lock needs to be gained/released. In these cases it make sense to apply the DRY principal and parcel those actions together.

Within the private context, its still possible for the other functions in the family to side-step these 'getters and setters' and manipulate the data structure. Hence why I think of them more as accessors and manipulators. You could access the data directly, or rely on another family member to get that part right.

Protected Getters/Setters

In a protected context, its not terribly different to a public context. Foreign possibly rogue functions want access to the data-structure. So no, if they exist they operate like public getters/setters.

0

From C++ experience, The setter/getter is helpful for 2 scenarios:

  1. if you have to perform sanity check before assigning value to the member like strings or array.
  2. it can be helpful when function overloading is needed like int value to bool assignment when -1 (or negative values) is false. and vice versa for getter.

Apart form that, security is a valid point but its importance is limited to very few development applications like login or db access related modules. Why bother coding extra when only few people uses your module?

Not the answer you're looking for? Browse other questions tagged or ask your own question.