0

I am designing a role playing game. In such games there is a character that has a level. I found out that the level itself is an object. It has values like experience, the knowledge of how moch experience is needed for a level-up, and methods like improve() or gainExperience(). So the character should have a level object. A game-object could have a fight-method. When the character wins a fight, he gains experience. The game object has access to the player object. But the problem now is: All fields should be private. So I would have to write a getter for getting the level object to increase the experience which looks like unesseccary code to me. Is it an accepted way to set the level-field of the character object public, and access it like that:

player.level.gainExperience(value);

or is there a better way to access methods of fields that are also objects?

Edit My question is different from this one. While the quoted question is very general, mine refers to a concrete example, which limits the possibilities of answering, and makes an answer simpler and clearer

4

A possible answer would be to define that same method on the player, and delegate to the "level" object:

player.gainExperience(value);

public final class Player {
    private final Level level;
    ...
    public void gainExperience(int value) {
        level.gainExperience(value);
    }
}

You should try to avoid introducing "getters" as much as possible, and even if you think it's not possible, just try one more time. You will reap the benefits later.

  • But when you have a computer with a cpu and so on for example. And you have a mechanic that wants to overclock the cpu. The cpu is part of the computer, so its part of this object. In this case I think it would be better to write it like that: computer.getProcessor().overclock(value); instead of computer.overclock(). Because you also could overclock the graphics card which leads to confusion. Would you agree? – Henry Weinert Feb 12 '18 at 14:23
  • @HenryWeinert Nope. Read on the Law of Demeter. By doing this, you expose the fact that a Computer has a Processor to the outside world. If you decide that you do not need a separate class for a Processor and you want to implement it directly in the Computer class, you've just broken all the code that called getProcessor(). – Vincent Savard Feb 12 '18 at 14:52
  • If you are looking for an easy generic solution, unfortunately there isn't one. It seems to me like Player.gainExperience() is a fair business method, but even there I assumed things. In your Computer/Processor example I would have to know more to make a design decision. While the specific proposition of "Computer.overclock()" might be wrong, there are other ways to avoid a getter. Receiving the Processor objects directly, or calling it as part of another use-case from the Computer, etc... – Robert Bräutigam Feb 12 '18 at 14:52
1

You want to make your Fight object as simple as possible. If it knows that some fight participants are players, and players have levels and levels know about experience etc then its getting complicated.

But somewhere in your code, something has to know these things. I wouldn't lose any sleep over:

Main()
{
    var winner = Fight.WhoWins(player, monster1, monster2);
    if(winner == player)
    {
        player.level.gainExperience(100);
    }
}

Its when that access to the child object is buried deep down the object graph that it becomes obviously helpful not to expose it. eg

Attack(target)
{
     if(target.body.hitpoints < this.attacker.weapon.stats.damage)
     //what about attacking objects?
     //what about unarmed attacks?
     {
         this.attacker.level.gainExperiece(target.monsterType.expValue);
         //what if the attacker isnt a player and thus hasnt got a level?
         //what if the target isnt a monster
     }
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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