83

I’m still really new to learning to program. Just learning the syntax for a few programming languages at the moment.

The courses I viewed for C# and Java touched only very briefly on getters & setters and it still didn’t make an awful lot of sense to me. So I researched them further and found that the whole subject of getters & setters is a lot more debated than I could believe. For every argument & example both for and against getters & setters there was a counter argument, saying that it was wrong, the code was a bad example etc. and I still didn’t know who to agree with or even fully grasp the jargon behind it.

So I’m really not sure what to go for at the moment. So I’m going to post my take on what getters & setters really are given what I’ve read and if there’s anything I’ve got wrong then please tell me. Then I have a few more questions that I haven’t found any answers for anywhere.

My take on getters & setters

FOR:

  • Getters and setters are methods declared within a class and applied to fields within said class, and control what other classes can access and modify these fields.

  • They’re used on fields which need to be accessed from outside their class, but at the same time cannot let anything have access other than what needs access.

  • When programmers talk about “if you make a field public then ANYONE can have access to them” by anyone they’re not necessarily talking about hackers or the user of your finished program. They’re talking about any other programmers who are working on the same program (or yourself) creating something which accidentally creates side effects which modify that class. Then you not being able to work out what is causing that change.

  • As well as controlling access they can do other things such as validate any input to the field before it is added (Mike Dane aka Giraffeacademy has used the example several times that a movie can only have 3 age ratings, so adding into the setter a method which checks the rating of a movie before it is added is a good side effect of a setter). In the same example, it can also improve the maintainability of your program, for example if a fourth rating is added, you can modify any objects where the new rating applies to just by adding it to the setter, rather than going through each movie individually.

AGAINST

  • Many programmers nowadays are strongly against the use of getters and setters. They argue that it ruins the encapsulation of your objects and makes code noisy and unreadable. Also that they encourage programmers to think of objects as data structures.

  • I’ve seen some arguments that they are now somewhat obsolete as some programming languages such as Python, which doesn’t need to use getters & setters. Also some IDE’s make it easy to see where side effects are taking place.

  • The main argument I’ve seen against them is that they’re just poor design. Code and classes should be clean and organised in a way that fields are only accessed outside the class when it absolutely needs to be, and getters and setters should only be used as a last resort.

  • An idea I saw recently is that you should start off making every field you create private. Then find everything which needs to be accessed outside the class and if there’s no other way around it, add a getter and/or setter to it.

The final, neutral argument I’ve seen is that you shouldn’t be adding things to your code that you don’t understand or don’t know if you’re going to need or not. That I absolutely agree with. But obviously I need to know if they’re going to be useful to me or not when I actually create something.

So if I’ve got anything wrong then please let me know, and I still have a few questions:

  • What parts of your program would you actually use getters and setters on? The examples I’ve seen online use classes such as ‘Dog/Ball’ and ‘Person’ which really aren’t much use to me. I’m thinking you would use them if you had a class for ‘Accounts’ and a different class for ‘Settings’.. the settings class would need to access the Account’s user name if the username requested to change it.. right?

  • Going with that example, if getters and setters are created to prevent someone from being able to change a variable through a side effect, what kind of code could actually change a user’s name as a side effect accidentally? Surely the only kind of areas in your program that could modify an accounts username are setUsername, displayUsername and changeUsername, and nothing else would ever need to go near those variables.

  • Given the debate I’ve found surrounding getters & setters why do courses and tutorials touch so briefly on them only just teaching you the syntax for them, and not arguing the cases for and against or even providing actual real world examples? (See note before about dog/ball). Are they too biased of an opinion? Or am I just looking into one topic way too much?

As I said I’m still so new to programming, so I’m probably either too inexperienced or thinking about it way too much. I just want to be absolutely clear on what I’m adding/not adding to my programs before I release them to the world.

Any help much appreciated. Have a good day.

21
  • 14
    While this is interesting question, I think the answer would be too opinionated. I'm sure you can find here people from both sides of the argument. For me, one thing I agree highly is the "Don't add properties until you absolutely need them." And C# being my main language, I still use them frequently.
    – Euphoric
    Commented Sep 29, 2020 at 19:34
  • 17
    It sounds like you are overthinking it. If you are not sure you need a getter/setter then you probably don't. Getters/setters are appropriate in some circumstances and not others, so it is hard to say without further context if you should use then. What is they problem you are trying to solve?
    – JacquesB
    Commented Sep 29, 2020 at 19:41
  • 7
    It's not that getters and setters are inherently evil. This is not about a single class, but about maintainability problems which arise in a larger system where classes/objects interact. The problem is coupling; the more classes know the details of each other, the more they become coupled in a way that makes change harder, and increases the overall complexity. This essentially happens "on its own" as the project ages, unless steps are actively taken to battle this entanglement. 1/2 Commented Sep 30, 2020 at 12:12
  • 3
    At some point in my career I decided to program my thesis project without getters/setters. Everything went swimmingly until later in the project I realized I needed to execute some code each time some members were accessed. I had to waste a few good hours replacing member access with a call to an appropriate getter (all of this happened in Java).
    – Spidey
    Commented Oct 1, 2020 at 11:34
  • 6
    @ProjectDiversion Two good rules of thumb: (a) it's better to call a method than to access a field (for reasons others have given), (b) think hard about method names, rather than blindly using getFoo and setFoo. For example, instead of Account::getBalance why not call it Account::balance? Would it be better to replace Account::setBalance with separate Account::deposit and Account::withdraw methods? etc.
    – Warbo
    Commented Oct 1, 2020 at 15:07

12 Answers 12

133

I’m still really new to learning to program. Just learning the syntax for a few programming languages at the moment.

And that is actually the problem here - you approach this way too much from a syntactical point of view. What you need to learn first is solving problems with programs. When the problems get larger, the programs will get larger and require more structure. That will bring you to a point where you need

  • data structures and data abstractions

  • functional abstractions

  • functions which operate on specific data structures, so the data structures might become classes, and the functions become member functions of that classes.

At that point, you will have to learn about how to design the public API of a class to create a good abstraction, for reaching a certain goal. You will also start to learn why making members "private" by default is a really good idea. If you work in some context of a real problem, you will know the precise requirements for your classes and their API, so you can decide which parts / functions / properties can stay private, and which not.

That will be the point in time where you may notice a very frequent requirement for classes: getting external access to some state information of the object (either read access - for which a getter is fine, or also write access, for which an additional setter will be required). Such state often corresponds to the content of a private member variable. However, that is not mandatory, getters and setters can also deliver (or change) values/state which are not stored directly in a member variable, but can be derived or calculated indirectly.

So in short: you do not decide about using or not using getters and setters by a pro/con list. Getters and setters are just tools which help you to solve some problems (specifically the problems you listed in your FOR section). One decides about their usage depending on if the actual problem requires them, and if they fit well to the kind of abstraction one wants to build by a class.

11
  • 4
    Well said. You get some very different problems when working on a codebase of tens of thousands of lines than you get from the small, manageable programs you write when you're learning. Anything that helps tame that complexity, anything that lets you work on small parts in isolation, is something that will reduce bugs and improve productivity. Strong encapsulation is one such tool — it's one of the main reasons why object-oriented programming has become so successful.
    – gidds
    Commented Sep 30, 2020 at 13:35
  • 1
    Getting access to private member variables is not a frequent requirement if you're doing object-orientation, exactly the opposite, it is pretty rare. "Getters and setters are just tools", while technically correct, is therefore extremely misleading. Commented Oct 1, 2020 at 8:27
  • 1
    @RobertBräutigam: at least it is so frequent that in C# language designers decided to introduce an own language feature for it (properties). It is so frequent Fowler has a an own refactoring in his catalog. There should be nothing misleading here, if you don't try intentionally to misread what I wrote.
    – Doc Brown
    Commented Oct 1, 2020 at 8:42
  • @DocBrown You wrote it is a "frequent requirement for classes", not that it is frequently done. I agree that it is frequently done, that is why all the languages want it incorporated, they just follow the majority. The majority of designs however are data structure-services type designs, not object-oriented ones. This difference matters a lot. Commented Oct 1, 2020 at 9:02
  • 2
    @deividaspetraitis: Here is a good list, I think I have read (or at least used) several of the top 30 fo them.
    – Doc Brown
    Commented Oct 2, 2020 at 4:43
35

Getters and setters allow the programmer to change the implementation of a class later on more easily. If the class is used elsewhere, and if there are no getters and setters, then the programmer has to change every other class which uses it. With getters and setters, the using classes can remain unchanged.

Imagine you have a class called BankAccount with a balance and a transaction history. There is another class which retrieves BankAccount objects from the database.

You find out that your program is too slow. After some profiling, it is the transaction history which takes a long time to load, yet almost all uses of the bankAccount query the balance only. Fortunately, there is a getter.

public List<Transaction> getTransactionHistory() { 
    return transactionHistory; 
}

You can simply change this getter and the way the bank account is initially loaded.

public List<Transaction> getTransactionHistory() { 
    if (transactionHistory == null) {
        loadTransactionHistory();
    }
    return transactionHistory; 
}

People who use your class don't see a difference, except that the initial loading got much faster and the subsequent call to the getter got slower.

Or you find that saving BankAccount objects back into the database takes a lot of time, even if most of the time nothing has changed. Fortunately, there is a setter on both balance and transaction history.

public void setBalance(int balance) { 
    this.balance = balance;
}

You simply add a new field, a boolean called isDirty.

public void setBalance(int balance) { 
    this.isDirty = true;
    this.balance = balance;
}

And when it comes to persisting the object again, if !isDirty you can skip the persisting.

4
  • 4
    Also, validation can be added into property setters. Also firing events, say when the property has been changed. It's quite common for user interface elements to subscribe to "PropertyChangedEvent" which is fired from the setter if the new value does not equal the old one for example. Commented Oct 1, 2020 at 6:08
  • This answer gets much more to the point than the more upvoted answers. Having setters and getters allows you to modify the behavior without modifying the outside interface, which is very, very important.
    – user304877
    Commented Oct 2, 2020 at 6:55
  • I would just add what is kind of implicit here: if you had a public member called from somewhere else, if you change it to a getter to implement this, you would need to update every assembly calling it, as a getter is a method call and not just a variable access. If it's only accessed from within your solution, then this is probably not much of an issue.
    – Andrew
    Commented Oct 8, 2020 at 16:39
  • 1
    @Andrew, added.
    – o.m.
    Commented Oct 9, 2020 at 4:55
23

Getters and setters make accessing fields into their own methods. When you're in Java you have to do this up front or when you decide to do it later you change the interface. In C# they have lovely properties so your clients won't care when you decide to make your public fields private.

These let you detect when something is accessing your fields. Public fields can't do that.

This is why getters and setters exist. It's certainly not that they provide encapsulation. They don't. They just let you detect when someone is breaking your encapsulation. They don't make you object oriented. They don't enable polymorphism. But they still exist for a reason.

Use getters when you can't move the method that needs access into the class with the data. If you can you should under OO. This happens when you're up against a boundary like code you don't control. You can also use a collection in these cases but using getters provides type safety that collections don't offer. When up against the boundary problem a Data Transfer Object (DTO) full of getters is still better than a pile of public fields.

Use setters when you have to mutate the class during its lifetime. It's better to be immutable but somethings can't be. Deserializers used to require this but most no longer do. Immutable objects are great but try to get two nodes to point at each other without a setter.

Much as I hate how they break encapsulation I have to admit they sometimes have their uses. I use them in behaviorless DTOs. I keep them out of my behavior objects. I don't like hybrids that try to be both.


My take on getters & setters

FOR:

  • Getters and setters are methods declared within a class and applied to fields within said class, and control what other classes can access and modify these fields.

No, access modifiers (public, private, protected, default) do that on their own. This doesn't explain the existence of getters and setters.

  • They’re used on fields which need to be accessed from outside their class, but at the same time cannot let anything have access other than what needs access.

No, getters and setters have no idea what is accessing them. Well, unless you're peeking at the call stack with some reflection magic.

  • When programmers talk about “if you make a field public then ANYONE can have access to them” by anyone they’re not necessarily talking about hackers or the user of your finished program. They’re talking about any other programmers who are working on the same program (or yourself) creating something which accidentally creates side effects which modify that class. Then you not being able to work out what is causing that change.

This is correct. Information hiding, as this is called, isn't about security (unless someone adds some toys that make it that way). This is about protecting a chunk of code from being used any old crazy way rather than through its proper interface. That way you know what you're breaking when you change it. This is why maintaining real encapsulation is important. Access modifiers encourage that by making clear what is private and what is public. "Anyone" really just means coders working on other classes.

  • As well as controlling access they can do other things such as validate any input to the field before it is added (Mike Dane aka Giraffeacademy has used the example several times that a movie can only have 3 age ratings, so adding into the setter a method which checks the rating of a movie before it is added is a good side effect of a setter). In the same example, it can also improve the maintainability of your program, for example if a fourth rating is added, you can modify any objects where the new rating applies to just by adding it to the setter, rather than going through each movie individually.

Validation is something your constructor can do. You don't need it in setters if you don't have them. Anything that might invalidate your state should trigger validation. Limit what can invalidate you.

AGAINST

  • Many programmers nowadays are strongly against the use of getters and setters. They argue that it ruins the encapsulation of your objects and makes code noisy and unreadable. Also that they encourage programmers to think of objects as data structures.

I'm strongly against brainless use of getters and setters on every field. It ruins object orientation because there's no polymorphism. I want to tell something to do something and not have to know exactly what it is or what it will do. I want something else to worry about that. I don't get that if I poke my nose into every private thing that exists.

  • I’ve seen some arguments that they are now somewhat obsolete as some programming languages such as Python, which doesn’t need to use getters & setters. Also some IDE’s make it easy to see where side effects are taking place.

What python doesn't use is enforced access modifiers. They just mark their private fields with names that start with underscores. "We're all adults here" means you'll behave and respect that right?

  • The main argument I’ve seen against them is that they’re just poor design. Code and classes should be clean and organised in a way that fields are only accessed outside the class when it absolutely needs to be, and getters and setters should only be used as a last resort.

Properly encapsulated behavioral objects shouldn't let you know that those fields even exist. They provide an interface that you use to tell them to do things and they do it. They might use those fields to make decisions but you don't need to know that.

  • An idea I saw recently is that you should start off making every field you create private. Then find everything which needs to be accessed outside the class and if there’s no other way around it, add a getter and/or setter to it.

No. This is just pretending it's OK as long as you feel guilty about it. It's also promoting the idea that once a field is public it must stay that way. Learn to move what needs the field into the object that has it. If the field value must be sent somewhere else do the sending yourself. Don't let just anyone in here to get it.

The final, neutral argument I’ve seen is that you shouldn’t be adding things to your code that you don’t understand or don’t know if you’re going to need or not. That I absolutely agree with. But obviously I need to know if they’re going to be useful to me or not when I actually create something.

Add getters and setters to Java to keep people from directly accessing fields (thus, offer no public fields). C# has properties that makes that a non issue. But if you're trying to be object oriented try to keep people from touching your fields at all.

  • What parts of your program would you actually use getters and setters on? The examples I’ve seen online use classes such as ‘Dog/Ball’ and ‘Person’ which really aren’t much use to me. I’m thinking you would use them if you had a class for ‘Accounts’ and a different class for ‘Settings’.. the settings class would need to access the Account’s user name if the username requested to change it.. right?

Getters and setters solve problems that are difficult to realistically recreate in an example.

  • Going with that example, if getters and setters are created to prevent someone from being able to change a variable through a side effect, what kind of code could actually change a user’s name as a side effect accidentally? Surely the only kind of areas in your program that could modify an accounts username are setUsername, displayUsername and changeUsername, and nothing else would ever need to go near those variables.

Getters and setters are not created to prevent changing variables through side effects. They're created so that you can detect that variables have been changed or read.

  • Given the debate I’ve found surrounding getters & setters why do courses and tutorials touch so briefly on them only just teaching you the syntax for them, and not arguing the cases for and against or even providing actual real world examples? (See note before about dog/ball). Are they too biased of an opinion? Or am I just looking into one topic way too much?

Probably because the debate is still raging. They prefer to teach people what they can prove.

12
  • 15
    "you can't set a breakpoint on a field" that depends on the language
    – Lie Ryan
    Commented Sep 29, 2020 at 21:53
  • 16
    and the debugger; similarly as data-breakpoints. Commented Sep 30, 2020 at 7:38
  • 2
    The discussion is not between setter/getters vs. public fields, it's between setters/getters/public fields vs. proper encapsulation. The difference between using setters/getters and public fields is mostly irrelevant, but the difference between those and object-orientation is so ground-braking that we still discussing after 50 or so years, and still largely getting it wrong. Commented Sep 30, 2020 at 12:55
  • 2
    @SirTechSpec if info is part of foos state it shouldn’t be made part bars state. See “single source of truth”. However It can be operated on by the method you pass it to. For example foo can call bar.print(info) without knowing or caring how bar will print it. Commented Sep 30, 2020 at 19:26
  • 1
    In all seriousness, what's the difference between Java's public fields and Scala's and Kotlin's case/data class fields? Both cases are anemic data containers. Commented Oct 1, 2020 at 12:47
15

I am one of the software engineers who advocates suspicion for getters and setters, but only because of how they are used today. The reason I object is mainly that application programmers have developed the bad habit of generating getters and setters for every field without considering whether or not each getter or setter is necessary.

Furthermore, as you mentioned, the default access modifier for generated getters and setters, by default in many IDE's, is public.

Some languages do not even provide access control to fields (like Python) and in others like Java it is common to use libraries like Lombok to short-circuit type-safety and encapsulation.

In some cases, application developers literally could change many classes over to public fields, delete all the getters and setters, and have equivalent functionality to what they have today while removing hundreds of lines of potentially buggy code from their applications.

Both the existence of unnecessary getters or setters, and too-relaxed access modifiers on them, have created a significant percentage of the bugs I have seen in my seventeen-year career.

Nevertheless, as others have pointed out, getters and setters themselves are a different topic than access control and immutability, which are both more important to good application design.

A library developer will pay the most attention to getters and setters because they pay the highest price for problematic designs. In their context, even access to read-only fields must be controlled through getters because at least then they can keep one consistent library API while being able to modify the implementation underneath as necessary.

Thankfully, the good news is that most languages are evolving with new higher-level constructs that provide the ability to enforce good design for various use cases. Examples include C# properties and Scala case classes.

In short: good object-oriented design is subject to the context of many factors (application vs. library, available language features, open-source vs. private) and there is no single dogma that applies in all cases.

6
  • How would one know in advance if getters/setters are required or direct access is sufficient? I see them as preparation for future refactoring. Of course modern IDEs will help with simple signature changes, but it still clutters up the merge request if you change not just one class but all other classes which use it.
    – o.m.
    Commented Oct 2, 2020 at 8:56
  • 2
    Rather than decide between adding getters/setters or providing direct access, I would advocate neither as the first step. Commented Oct 2, 2020 at 18:09
  • 2
    What can be private should be private, but what cannot be private should use getters instead of direct access.
    – o.m.
    Commented Oct 3, 2020 at 4:49
  • Ah, the problem is Java syntax. Most modern languages (Java is more than 25 years old now) have setters & getters generated by the compiler. There are ways to do the same in Java using annotations, e.g. with Lombok. However, sooner or later Java will either evolve radically (not a trivial change every few years) or people will abandon it for other languages, be it Kotlin, C# or others.
    – Sulthan
    Commented Oct 5, 2020 at 9:14
  • @Sulthan Java has a feature like that already. It's called records. Commented Oct 6, 2020 at 15:28
8

When you're learning a new language and you're not sure about programming style, it might be good idea to take a look at the core libraries of the language. They might not always be a perfect model, but they're most likely way better than most of the code you'll see elsewhere.

Adopting a similar programming style will be beneficial. Your code will be easy to understand for anyone who is familiar with the language. If fields are not directly exposed in core libraries, then you could avoid exposing fields too just to follow the convention. Conventions are very important.

Sticking to the style of important libraries might be beneficial even when you're experienced enough to form your own opinion and even when you'd personally prefer an alternative style. If really want to abandon conventions, you can always do it in a private hobby project.

5

The main difference between using setters/getters/direct access and properly encapsulated objects, is a design question not a syntactical one.

The former ones are basically a holdover from our procedural past, that we can't seem to shake. It is much easier to imagine a set of instructions on some data that the CPU has to execute. This thinking results in data structures and algorithms. Therefore those who think this way will often need access to data and usually can't imagine how else they could write a program.

Object-orientation is about decomposing a problem into individual agents (objects) that do stuff. Not just any (technical) stuff, but business stuff, something that fulfills some requirement that is important for users/business people. This is why it is hard to have examples, because the methods you put in an object are determined by your requirements, not the object itself. A Book doesn't automatically have Pages or even a title, only if there is a functionality that needs it. And this functionality needs to be in the Book, therefore there will be no need to access those from the outside.

From the above it follows, we only provide access to pure data (setter/getters/direct access) if we don't, or even can't know what the supported functionality should be. This happens on the "edges" of your code. For example you are writing an http-client, you'll (probably) have to provide the raw content to the caller, because you don't (can't) know how that will be used. Inside a software, like a web-application or similar this should never happen.

I think it is awesome that you think about these things. And remember, most resources out there still didn't quite made the leap to object-orientation, so you'll have to use your own judgement, and later, you own experience.

3
  • If I got you right, something like a Book class needs to contain all the functionality which is related to books. That does not make much sense to me. In any non-trivial program which deals with books, a Book will be only one component of many. Pages or even a title are properties of a book which can (and often should) be processed by other components. Cramming all functionality which is related to books into a Book class, in my experience, leads exactly to the kind of overcharged "OO" designs which failed frequently in reality.
    – Doc Brown
    Commented Oct 1, 2020 at 15:06
  • I've never saw projects even try moving non-trivial functionality into "Book" objects, let alone go overboard with it as you describe. And I've been doing enterprise development since the late 90s. It's possible that you have more experience with such projects, I don't know. I think it is more likely that most OO concepts, as most FP concepts for that matter, are just so alien to the average procedural/imperative developer, that there is an understandable lack of imagination of how those would look like. That's not a critique, I'm honestly trying to change that, with articles and comments. Commented Oct 1, 2020 at 16:48
  • Did I understand you correctly: in over 20 years, you have never seen classes growing so large that any maintenance and further development became painful, if not impossible?
    – Doc Brown
    Commented Oct 1, 2020 at 19:40
3

I think you're combining two things here, using getters/setters and making a field public. There are essentially three options here:

  • add a private field
  • add a public field
  • add a private field with getter/setter

As a general rule fields should only be public if necessary, and you shouldn't expose any implementation details that the user of the class doesn't need to know by making fields public unnecessarily. Adding a getter/setter by definition also makes a field public, and some of your arguments are really about that part. But that is also independent of using a getter/setter, you have the same issues if you just make the field public.

I'm assuming C# here as I'm not entirely sure about the details in modern Java in this regard. C# has automatically generated getters and setters, which does minimize the boilerplate you'd usually have for trivial getters and setters that simply set a private field. In this case you would generally prefer to use autogenerated getters/setters instead of a public field. It adds hardly any noise, and it gives you the option to change the implementation without changing the public interface of your class and potentially breaking code using it.

In general you need to be careful to not do anything in getters and setters that a reasonable programmer would find surprising. Validation is fine, side effects that e.g. perform IO or affect other parts of your object are probably a very bad idea.

1
  • 2
    Note that both Java and C# support private on getters and setters. I think your description of having three options implies that accessibility is related to getter/setter, but they're actually orthogonal.
    – Brian
    Commented Sep 30, 2020 at 13:52
2

In addition to what has been said by others, I will add that there are two broad categories of uses I see for Java classes in my applications:

  • classes that encapsulate program logic about a certain area of the program (like the objects you read about in your programming textbooks!)
  • classes that exist only to hold data about an entity in the program

The latter kind have names like Customer, or Product, or Item, are generally filled up with data by reading data out of a database and creating one instance for each row of the result, or are filled in by a user with a web form. The data, once entered, is rarely changed, and there's little to no logic within the class.

For the first type, the classes that encapsulate program logic, generally your fields should be private and you shouldn't have getters and setters for the fields, except maybe for injecting dependencies or setting configuration options. This is real object-oriented code and you should take care to design a good public API.

For the second type, these are dumb data structures and all you need to do is (1) define the fields and (2) use your IDE to automatically create getters and setters for all of them. (Typically the frameworks and libraries you employ will require getters/setters.) You will hardly ever touch these again, although occasionally it becomes handy to modify a getter or setter for example to do some string formatting or to change a data type. It is pointless to worry about applying object-oriented design principles or design patterns to these cases -- they aren't really what the philosophers of those fields considered to be "objects" anyway.

1
  • @Walfrat Good point! I added a remark about that.
    – workerjoe
    Commented Oct 1, 2020 at 12:19
2

As others have pointed out, you are in places conflating access control (public, private...) with the question of whether to implement getters and setters (which, depending on the language, can themselves take access control modifiers). While these are of course related, it's important to be clear which you are focusing on at any point.

However, between the lines of that discussion there are also other, more fundamental questions that need answering:

What parts of your program would you actually use getters and setters on? The examples I’ve seen online use classes such as ‘Dog/Ball’ and ‘Person’ which really aren’t much use to me. I’m thinking you would use them if you had a class for ‘Accounts’ and a different class for ‘Settings’.. the settings class would need to access the Account’s user name if the username requested to change it.. right?

No. Not necessarily, anyway, and I would say probably not. But the question of how to update the username is one you would first want to consider as part of your overall design, and in the context of your overall data model.

For example, let's say there is a business requirement to maintain settings for our product (a website). These might be configuration settings (for administrators to set options controlling how the website behaves when users edit accounts) or they might be user settings (enabling website users to choose to view the site in a different language whenever they visit, or to choose a preferred navigation style).

And let's say there is also a business requirement for both users and administrators to edit Account records, changing such things as email address, postal address, telephone number and username. Now, it could be that in your data model, the Account field values (email address, username...) are defined as "settings" in some global repository (cue Windows Registry designers!). Quite likely though, your data model defines the Account field values not as "settings" but as properties of the Account entity. And from here, the question would not be whether to implement a getter and setter for username. The question would be, "Given that we're using object orientation here, and given the relationship between the Account entity and the entities that need to interact with it, what interface should Account expose to support these interactions? Because here's the thing: the answer might be "make username public", but actually it might be "provide an UpdateUsername method (or even an UpdateAccount method) that takes as parameters both the updated value(s) and some additional information needed any time an account is updated."

Like Dog and Ball, even Account doesn't lend itself well to examples that are universally right and wrong.

In summary, focusing on getter and setters and questioning them as you have done is valuable—as are many of the points on this subject noted in other answers. But don't just think about whether to expose a field directly or via a getter/setter; think first about whether it should even be exposed. Encapsulation is key here: which entities should be responsible for implementing the business logic, and hence which entities should have the low-level knowledge that a certain business rule is met by updating a certain field? Username is pretty clear but in other cases the meaning of a field can be less clear, or may be subject to subtle or complex business logic. The caller's view should be abstracted to a higher level that doesn't assume knowledge of the low-level implementation details. In such cases, exposing a field—whichever way you do it—is not sufficient.

1

You mentioned the thing about making fields public then anyone can mess with your data -- that's true, but the missing thing is that a lot of times you don't want a setter, just a getter, and in some languages (like Java) there's not good ways to make fields public and immutable.

public class Foo {

  public int a; // Anyone can see this, but they can also *change* it.

  public final int b; // They can't edit this since it's final!

  public final List<Integer> intList; // Even though this is final it is still mutable.

  // But using a getter we can return a read-only copy of the list to accomplish this.
  public List<Integer> getIntList() {
    return Collections.unmodifiableList(intList);
  }
}

Often times we think of getters and setters as simply returning the value as-is or setting the value as-is, and in many cases that's all it is. Sometimes you need more fine grained control though.

Also it helps to let you change your implementation details. Say you have a method that returns the date as "YYYY-MM-DD".

public class Bar {
  public String year;
  public String month;
  public String day;

  public String getDateString() {
    return year + "-" + month + "-" + day;
  }
}

But then you find out about LocalDate class and thing it's a much simpler way to store it so you change your class to this.

public class Bar {
  public LocalDate date;

  public String getYear() {
    return getDateString().substring(0, 4);
  }

  public String getMonth() {
    return getDateString().substring(5, 7);
  }

  public String getDay() {
    return getDateString().substring(8, 10);
  }

  public String getDateString() {
    return date.toString();
  }
}

This design is cleaner, and let's hypothetically say there's more methods that makes it even more useful for whatever reason. But oh no, you make this change and push the code and now one of your teammates is complaining about a compilation error. You had the fields as public before. Their code relied on it. Now you have to argue about if you need to keep the fields or if they have to change their code. But if you had not exposed the implementation details you would not need to worry. Everything that is public is essentially like a contract about how your code will work.

7
  • "Even though this is final it is still mutable." That's a flat-out lie. What it points to is mutable though. Don't perpetuate the inability to navigate indirection. Commented Oct 1, 2020 at 19:28
  • @Deduplicator that list is certainly mutable in that example. Am I misunderstanding you? Commented Oct 1, 2020 at 19:37
  • Yes. You are saying despite being final, it is still mutable. But intList is most certainly not mutable. What it points to is, but that's a different affair. Thus, I bemoan your perpetuation of the inability to differentiate levels of indirection, a most fundamental and crucial ability for any aspiring programmer. Commented Oct 1, 2020 at 20:55
  • @Deduplicator I get you're point, but I don't see the issue. When talking about non-primitive fields generally the terms "final" and "non-final" are used to say whether the field is mutable and the terms "mutable" and "immutable" are used to say whether the object behind the reference has mutable fields. Commented Oct 1, 2020 at 21:22
  • If that's the Java jargon, and you want to only talk in that group, that's fine. Other languages allow more levels directly, allow applying immutability beyond the outermost level, etc. Commented Oct 1, 2020 at 21:50
1

I still don’t fully understand getters & setters I’m still really new to learning to program. Just learning the syntax for a few programming languages at the moment.

Getters/setters/fields/function are all implementation details around getting and changing state. Unless you are designing or working on a public api, I would recommend that you simply follow the practice of whatever project you are working on or the guidance of teacher/co-workers.

Part of the reasons to use them or not are implementation details of the language, tools and libraries of the project. If you need to deserialize a string to a class and the deserialization library only uses properties, well, the class needs to have properties.

So, there’s no one size fits all answer, and you don’t have a strong opinion, use what those around you are using, and be willing to do so on whatever project you are working on, until you do develop a strong opinion.

-1

In C#/WPF, if you want to use data binding, you have to use properties. It doesn't work with fields.

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