What are the alternatives to public fields?

前端 未结 12 2716
刺人心
刺人心 2021-02-19 15:05

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 a

相关标签:
12条回答
  • 2021-02-19 15:44

    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.

    0 讨论(0)
  • 2021-02-19 15:45

    .... pathetic content omitted....

    EDIT

    sorry for beeing a little too pathetic -must be the pills... The other answers are quite relevant and good

    0 讨论(0)
  • 2021-02-19 15:47

    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.

    0 讨论(0)
  • 2021-02-19 15:49

    An advantage of using getters and especially setters is, that it is much easier to debug write access to the fields.

    0 讨论(0)
  • 2021-02-19 15:52

    If you have a private field with a method get() and a method set() that don't do anything other than retrieve and assign the value, you should just make the field public, as the field isn't really private, and the getters and setters only hurt performance. If the getters and setters check the value being set or if the value is allowed to retrieve, then go ahead and use getters and setters. e.g. If you have a variable private int width; and someone tries to put in -1 with a setter, and the setter makes sure it isn't negative, then that is a good use. For example:

    private int width;
    public int get(){
        return width;
    }
    public void set(int w){
        if (w < 0) throw new RuntimeException();
        else width = w;
    }
    

    This would be a good use of getters and setters. Otherwise, they hurt your performance if the only thing they do is assign or get the value without anything else.

    So to make a long story short:

    Use getters and setters when doing anything other than retrieving or assigning a value. Else, just use public fields.

    i.e.

    BAD:

    private int width;
    public int get(){
        return width;
    }
    public void set(int w){
        width = w;
    }
    

    GOOD:

    private int width;
    public int get(){
        return width;
    }
    public void set(int w){
        if (w < 0) throw new RuntimeException();
        else width = w;
    }
    

    GOOD if you don't want anything other than getting or setting:

    public int width;
    
    0 讨论(0)
  • 2021-02-19 15:54

    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.

    public void beDamaged(double damage)
    {
        this.health -= damage;
    
        if (this.health < 0)
        {
            this.health = 0;
        }
    }
    

    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:

    A player's health cannot be a negative number.

    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:

    public double health;
    

    With the health field being public, 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:

    Player player = new Player();
    player.health = -100
    

    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 field private.

    Now, the only way to affect the player's health would be through the beDamaged and gainHealth 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.

    0 讨论(0)
提交回复
热议问题