32

Encapsulation is hiding the data. I would like to hear some really interesting answers here.

What is the point behind keeping variables as private when we already declare public setter methods for variables?

I understand the usage of encapsulation but when we are making the setters as public what is the point behind keeping the variables as private, we can directly use public access modifiers.

Is it because we do not want others to know the exact way we are storing data or managing data on the back-end?

Danyal Sandeelo
  • 12,196
  • 10
  • 47
  • 78
  • And [here](http://stackoverflow.com/questions/4739597/getter-with-side-effect) is what could be regarded as the opposite question. – Tobia Tesan Sep 16 '15 at 13:31
  • I have large systems with hundreds of thousands or millions of lines of code without a single setter. I like it that way. – Michael Deardeuff Sep 16 '15 at 16:15
  • 1
    @McAdam331 Yes, right it is..the questioner has mentioned java but yes it is application to all the languages using getters and setters. This is an oop related aspect..thanks :) – Danyal Sandeelo Sep 16 '15 at 16:35
  • Because you get to choose what you want to be public in the setter. – johnny Sep 16 '15 at 16:48
  • Here is another way to look at it: http://www.cspray.net/programming/2012/05/13/stop-calling-them-getters-setters.html – Zsw Sep 16 '15 at 17:42

9 Answers9

34

Is it because we do not want others to know the exact way we are storing data or managing data on the back-end?

Yes, that's the point. It is related to the concepts of abstraction and information hiding too.

You provide a public setter that when invoked by the class client will have the effect that you have documented. It is none of the client's business how this effect is actually achieved. Are you modifying one of the class attributes? Ok, let the client know that, but not the fact that you are actually modifying a variable. In the future, you could want to modify your class so that instead of a simple backup variable it uses something completely different (a dictionary of attributes? An external service? Whatever!) and the client will not break.

So your setter is an abstraction that you provide to the client for "modify this class attribute". At the same time you are hiding the fact that you are using an internal variable because the client doesn't need to know that fact.

(Note: here I'm using the word "attribute" as a generic concept, not related to any concrete programming language)

Burke9077
  • 367
  • 1
  • 5
  • 20
Konamiman
  • 49,681
  • 17
  • 108
  • 138
  • abstraction is all about hiding the functionality ..this is some-how related to hiding the back-end mechanism, the way we SET the data.. Good explanation...:) – Danyal Sandeelo Sep 16 '15 at 08:45
  • 6
    Abstraction is about hiding _implementation_ not functionality. – codemonkey Sep 16 '15 at 10:35
  • functionality is dependent on implementation.. so yes it goes back on the same thing.. – Danyal Sandeelo Sep 16 '15 at 12:04
  • 1
    However, there are (many?) programming languages that allow to create setter/getter attributes, so they look like variable accesses but are actually method calls. The syntax for accessing is the same. So in these languages, you don't really need to hide anything if you only care about being able to modify your class to use a different internal representation. – Bergi Sep 16 '15 at 12:48
  • Another reason for starting with a public setter that doesn't do anything than alter the private variables could be that at some point you may want to "police" the values being set. – TripeHound Sep 16 '15 at 15:51
26

I fully agree with Konamiman's answer, but I'd like to add one thing:

There are cases where you really don't want that abstraction. And that's fine.

A simple example I like to use here is a class for a 3-dimensional float vector:

class Vector3f {
public:
    float x;
    float y;
    float z;
};

Could you make those fields private and provide setters instead? Sure, you could. But here you might argue that the class is really just supposed to provide a tuple of floats and you don't want any additional functionality. Thus adding setters would only complicate the class and you'd rather leave the fields public.

Now, you can easily construct scenarios where that might bite you later on. For instance, you might one day get a requirement that Vector3fs are not allowed to store NaNs and should throw an exception if anyone tries to do so. But such a hypothetical future problem should not be enough to justify introducing additional abstractions.

It's your call as a programmer to decide which abstractions make sense for the problem at hand and which ones would only get in your way of getting the job done. Unnecessary abstractions are over-engineering and will hurt your productivity just as much as not abstracting enough.

Bottom line: Don't blindly use setters everywhere just because someone claimed that's good practice. Instead, think about the problem at hand and consider the tradeoffs.

Community
  • 1
  • 1
ComicSansMS
  • 51,484
  • 14
  • 155
  • 166
  • 2
    Good one, that's what I say, depends on what you need actually. – Danyal Sandeelo Sep 16 '15 at 10:56
  • Getting the balance right (between over- and under-abstraction) can be difficult. Getting it wrong _in either direction_ can harm productivity. – TripeHound Sep 16 '15 at 15:48
  • A more relevant scenario IMHO would be the possibility that if a Vector provides a `SetLocation` function, a derivative of vector might be able to trigger some action when its location is changed. For example, a `MoveReportingVector` might accept in its constructor a `MotionReporter` [an interface] object and invoke its `ReportMotion` method whenever something calls `SetLocation` on the `MoveReportingVector`. I wish Java had a way to declare that non-final fields were publicly readable but locally modifiable, to facilitate such types, since such semantics are often appropriate. – supercat Sep 16 '15 at 16:47
12

Because by encapsulation we provide single point of access. Suppose you define a variable and its setter as follows

String username; 

public void setUsername(String username){
this.username = username;
}

Later you like to add some validation before setting username property. If you are setting the username at 10 places by directly accessing the property then you don't have single point of access and you need to make this change at 10 places. But if you have one setter method then by making a change at one place you can easily achieve the result.

Jawad
  • 408
  • 4
  • 11
7

Think about this : I'm representing a real life object, a Lion through a class. I'd do something like this.

class Lion {
    public int legs;
}

Now my class is needed by some other developer to create an object and set its legs field. He'd do something like this

Lion jungleKing = new Lion();
jungleKing.legs = 15;

Now the question is, Java won't restrict him to setting any number more than 4 as the number of legs for that object. It's not an error, and it'll run just fine. But it's a logical blunder, and the compiler won't help you there. This way a Lion may have any number of legs. But if we write the code this way

class Lion {
    private int legs;
    public void setLegs(int legs){
        if(legs > 4){
            this.legs = 4;
         }
        else this.legs = legs;
    } 
}

Now you won't have any Lion with more than 4 legs because the policy of updating the fields of the class has been defined by the class itself and there's no way anyone not knowing the policy is going to update the legs field because the only way to update the legs field is through the setLegs() method and that method knows the policy of the class.

zulkarnain shah
  • 971
  • 9
  • 20
6

Although Konamiman's answer is spot on, I'd like to add that, in the particular case of public setters versus directly exposing public fields you are asking, there is another very important distinction to keep in mind apart from information hiding and decoupling implementation from the public surface, or API, of a class; validation.

In a public field scenario, there is no way to validate the field's value when it's modified. In case of a public setter (be it a Foo {get; set;} property or a SetFoo(Foo value)) method you have the possibility to add validation code and launch required side-effects and this way ensure that your class is always in a valid or predictable state.

Community
  • 1
  • 1
InBetween
  • 32,319
  • 3
  • 50
  • 90
3

What if you do want to a range check before assignment? That's one of the cases I use setters and getters

Ali Burak Kulakli
  • 562
  • 1
  • 5
  • 16
2

More or less simple and realistic example I encountered in practice is an Options class, which has a lot of setters and getters. At some point you might want to add new option which depends on others or has side effects. Or even replace group of options with Enum. In this case setA function will not just modify a field, but will hide some additional configuration logic. Similarly getA will not just return value of a, but something like config == cStuffSupportingA.

anxieux
  • 757
  • 5
  • 14
2

Wikipedia has a good overview of [mutator methods(https://en.wikipedia.org/wiki/Mutator_method), which is what setter methods are and how they work in different languages.

The short version: if you want to introduce validation or other logic that gets executed on object modification it is nice to have a setter to put that logic in. Also you may want to hide how you store things. So, those are reasons for having getters/setters. Similarly, for getters, you might have logic that provides default values or values that are dependent on e.g. configuration for things like Locale, character encoding, etc. There are lots of valid reasons to want to have logic other than getting or setting the instance variable.

Obviously, if you have getters and setteres, you don't want people bypassing them by manipulating the object state directly, which is why you should keep instance variables private.

Other things to consider include whether you actually want your objects to be mutable at all (if not, make fields final), whether you want to make modifying the object state threadsafe with e.g. locks, synchronized, etc.

Jilles van Gurp
  • 7,927
  • 4
  • 38
  • 46
2

Setting fields as private documents a powerful fact: these private fields are only directly used within the current class. This helps maintainers by not having to track down field usage. They can reason better on the code by looking at the class and determining that the effects on and from these fields with the class' environment go through public and protected method calls. It limits the exposure surface on the class.

In turn, defining a "setter" for a private field is not about giving it publicity again. It is about declaring another powerful fact: an object belonging to this class has a property that can be modified from the outside. (The terms object and property are used in the sense of a bounded part of the whole and an observable fact about this part, not in the OOP sense)

Why then declare a "setter" on a field when making the field public would suffice? Because declaring a field not only binds a name to a property of the objects of the class, but also commits to use memory storage for this property.

Therefore, if you declare a "private field with a setter", you declare three things:

  • You declare that the name you gave to the field/setter cluster represents a property of the object which is of interest when the object is seen as a black box.
  • You declare that the value of this property is modifiable by the environment of the object.
  • You declare that in this particular concrete class, the property of the object is realized by committing some memory storage to it.

I advocate that you never make your fields private with getters and setters indiscriminately. Fields are for describing storage. Methods are for interactions with the environment. (And the particular case of "getters" and "setters" are for describing properties of interest)

Laurent LA RIZZA
  • 2,905
  • 1
  • 23
  • 41