-2

Everywhere is said that a private member can only be accessed from inside the same class, but at the same time, we can access the private member using getters and setters, therefore my question is:

What's the difference between having a private member and access it with getters and setters, and making the a member public and access it as well?!

Thanks.

Ian Mozz
  • 19
  • 1
  • 1
    Does this answer your question? [Is it bad practice to use public fields?](https://softwareengineering.stackexchange.com/questions/161303/is-it-bad-practice-to-use-public-fields) – gnat Feb 13 '21 at 15:45
  • 1
    I think [When are Getters and Setters Justified](https://softwareengineering.stackexchange.com/questions/21802/when-are-getters-and-setters-justified) is a better duplicate, in particular this bit from the accepted answer "What does break encapsulation is automatically adding a getter and a setter for every data member (every field, in java lingo), without giving it any thought" which seems to be the original poster's problem here. – Philip Kendall Feb 13 '21 at 15:55
  • What about if you **don't** make the getters and setters? – user253751 Feb 15 '21 at 12:04

2 Answers2

3

There are two arguments why you'd rather not expose public fields:

  • This limits future evolution of your design, assuming you need to offer a stable API.
  • This tends to lead to higher coupling between components, in particular to more complex data flows between components. And complexity leads to bugs.

Let's first discuss API stability.

There are two different kinds of codebases: one kind contains applications and in-house code. Everything is under your control and can be refactored freely. The other kind is a library with external consumers. Now you need to think about API stability, because you can't just change stuff. Code that worked with the old API should continue to work with the new API.

In applications, API stability doesn't matter because you can always refactor anything, and all dependent code along with it. Much of the OOP architecture advice you might read doesn't apply to applications.

Libraries are more tricky. Your first public design should be close to the ideal design, or at least allow opportunity for future evolution in a backwards-compatible manner. When we have a public member variable, we commit to there always being this variable. The variable will also accept any value when set, except as restricted by its type.

Properties and accessor methods are much more flexible. For example, we can remove the variable and re-compute it on the fly. Or we can add validation code. Or we can trigger events when a variable is updated. Since properties and accessor methods allow us to supply arbitrary code, this is much more flexible. In C#, a class that is part of a public API should almost always use auto-properties in place of public fields due to this future-compatibility aspect.

Another nice aspect in C# is that properties can be part of interfaces. This may also help with creating loosely coupled interfaces between components. This works because properties are just a different syntax for special methods.

The other aspect I mentioned is that using methods can lead to simpler data flows and less coupling between components.

One reason is that methods/properties let us separate the public API from our private implementation. E.g. we might not want to have other components assign to a field directly. In that case, a private set property might be very useful.

But allowing unrestricted getting/setting might not be a particularly good API for our object. An object should not be a bunch of named fields (whether as plain fields, properties, or getters/setters), but should provide some capabilities to its users. We should be able to tell an object to just do a thing, not ask the object for all data necessary so we can do the thing ourselves (see Tell-Don't-Ask by Martin Fowler).

amon
  • 132,749
  • 27
  • 279
  • 375
1

Also: "sometimes it makes perfect sense to use getters and setters, even for purely-private fields." And that of course depends on: "what is this field?"

For instance: "this value is actually computed, and therefore I could fill my code with calls to some private function." Well, a "getter" and maybe a "setter" is actually the same thing ... but it might make your code read a whole lot cleaner. They let the writer of source-code ignore the fact that there is a function-call involved, while also concentrating the implementation into one place so that, when necessary, you can easily change it in that one place. "Just do whatever your source-code writers prefer."

P.S.: A "getter/setter" is also a great place to hide assert() calls.

Mike Robinson
  • 1,765
  • 4
  • 10