I am programming a game in java, and as the question title suggestions i am using public fields in my classes. (for the time being)
From what i have seen public fields are bad and i have some understanding why. (but if someone could clarify why you should not use them, that would be appreciated)
The thing is that also from what i have seen, (and it seems logical) is that using private fields, but using getters and setters to access them is also not good as it defeats the point of using private fields in the first place.
So, my question is, what are the alternatives? or do i really have to use private fields with getters and setters?
For reference here is one of my classes, and some of its methods.
I will elaborate more if needs be.
public double health;
//The player's fields.
public String name;
public double goldCount;
public double maxWeight;
public double currentWeight;
public double maxBackPckSlts;
public double usedBackPckSlts; // The current back pack slots in use
public double maxHealth; // Maximum amount of health
public ArrayList<String> backPack = new ArrayList<String>();
//This method happens when ever the player dynamically takes damage(i.e. when it is not scripted for the player to take damage.
//Parameters will be added to make it dynamic so the player can take any spread of damage.
public void beDamaged(double damage)
{
this.health -= damage;
if (this.health < 0)
{
this.health = 0;
}
}
EDIT: For checking purposes, this is what my Weapon
class looks like now: (Code sample is not working for some reason, so it does not look right.)
private final double DAMAGE;
private final double SPEED;
public Weapon(double initialDmg,double initialSpd,String startName,double initialWg)
{
DAMAGE = initialDmg;
SPEED = initialSpd;
setItemName(startName);
setItemWeight(initialWg);
}
public double getSpeed()
{
return SPEED;
}
public double getDamage()
{
return DAMAGE;
}
As you can see, as the Weapon's
DAMAGE
and SPEED
do not need to be changed, they can be final's for the time being. (if, later in the game, i decided these values can be "Upgraded" so to speak, i may add setters then , with validation, or just make a new weapon with the upgraded values) They get set in the Weapon's
constructor.
Conclusion: getters and setters are fine, as long as they are used smartly, and only used when needed. (however)
It's common to use getters and setters instead of giving other objects permission to change your fields directly. That might not make any sense when you see that 99.99% of your getters and setters don't do anything except what you could have done with direct access to the fields. But what happens when you decide that when a player is damaged beyond a point, he drops half his inventory? Or you want to restrict how many backpack slots can be used by magical items? You either have to hunt down all the places in your code where you modify the fields, or, if you used getters and setters, you make the changes entirely in the class. That's the heart of object oriented programming - that you've encapsulated "knowledge" of what an object does within the object itself, not spread it out among all the objects that interact with that object.
private fields and setters and getters is indeed your best way to go.
Further note that this is in general good code in any language as it keeps your security nice and tight while also giving you a structure that is far easier to debug and maintain. (Don't forget to document btw!)
All in all, go with setters and getters, it's just good practice even if you find options.
.... pathetic content omitted....
EDIT
sorry for beeing a little too pathetic -must be the pills... The other answers are quite relevant and good
One of the core concepts of object-oriented programming is encapsulation -- that is, hiding an object's state (for example, the data in the object) from the outside, and letting the object handle it's own state.
When encapsulation is done well, the object's state can only be affected from the outside world through the interfaces provided by the object, such as methods the object has.
I think your code is already starting to use encapsulation.
Let's take a look at the code
Let's take a look at the
beDamaged
method.Here's we can see that this method will be called by the outside world, and the player's health will be affected. It also contains logic, so the health cannot be a negative number. The player's
beDamaged
method that you wrote is keeping the state of the object within the parameters that you defined as being the valid state.Let's infer something about the player
Now, from the above, I think I can infer the following about the player object:
Is what we inferred always true?
Let's see if this can always be true from the code you've provided.
Aha! We have a little problem here:
With the
health
field beingpublic
, the outside world can directly manipulate the field in order to place the player object's state into one that is probably not desired, by some code like the following:I'm going to guess that the player shouldn't be in a state where the
health
is a negative number.What can we do about it?
How could that have been avoided? -- by having the
health
fieldprivate
.Now, the only way to affect the player's
health
would be through thebeDamaged
andgainHealth
methods, and that's probably the right way for the outside world to affect your player's health.Which also means this -- when you make a field
private
, that does not automatically mean that you should make getters and setters for the field.Private fields does not necessitate getters and setters
Getters and setters are usually a way to directly affect a field that an object has, maybe with some validation to prevent bad input from making your object have a state that it shouldn't, but there are going to be times where the object itself should be in charge of affecting the data, rather than an outside entity.
About this:
The main problem is that many developers automatically generate getters and setters for all private fields. And if you're going to do that, I agree, you might as well keep the field public (no, public fields are even worse).
For every field that you have, you should check:
a) does it need a Getter (do other classes need to know the value of this field)
b) does it need a Setter (do other classes need to be able to change the value of this field)
c) or does the field need to be immutable (final), if so it must be initialized during definition or in the constructor (and it can obviously have no setter)
But you should hardly ever (exception: value objects) assume that all private fields will have getters and setters and let your IDE generate them all.
If you're not maintaining any invariants, then public fields are the way to go. If you do need an invariant across multiple members, then you need private fields and encapsulation.
But if you can't come up with any better names than GetFoo and SetFoo for the methods, it's a good clue that your getters and setters are probably worthless.